树是由n个结点组成的有限集合T;
二叉树是每个结点最多有两个子树的有序树;
二叉树不是树的特殊情形。
1、二叉树的链式存储结构
图a为最常用的二叉链表法。
2、几种遍历
(1)、先序遍历(DLR):从一棵二叉树根节点为起点,沿着二叉树外沿,逆时针走一圈回到根节点,路上遇到的元素顺序,就是先序遍历的结果。
(2)、中序遍历(LDR):可以理解为每个节点从最左边开始垂直掉到地上,然后从左往右数,得出的结果便是中序遍历的结果。
(3)、后序遍历(LRD):可以看成剪树叶,绕树一圈,如果发现一剪刀能剪下来的树叶(必须为一个树叶,及树叶一个个下来,不能一串下来),就把它剪下来,组成的就是后序遍历了。
(4)、层次遍历:对整个二叉树按从上到下,对每一层从左到右的顺序进行遍历(类似于队列的先进先出)。
二、二叉树的操作1、结构体定义
//二叉树结点
typedef struct BTNode
{
char element;
BTNode* left;
BTNode* right;
} BTNode,*BTNodePtr;
//带有多个指针的队列
typedef struct BTNodePtrQueue
{
BTNodePtr* nodePtrs;
int front;
int rear;
} BTNodePtrQueue,*QueuePtr;
2、初始化队列
//初始化队列
QueuePtr initQueue()
{
QueuePtr resultQueuePtr = (QueuePtr)malloc(sizeof(struct BTNodePtrQueue));
resultQueuePtr->nodePtrs = (BTNodePtr*)malloc(QUEUE_SIZE * sizeof(BTNodePtr));
resultQueuePtr->front = 0;
resultQueuePtr->rear = 1;
return resultQueuePtr;
}
3、判断队列是否为空
//判断队列是否为空
bool isQueueEmpty(QueuePtr paraQueuePtr)
{
if((paraQueuePtr->front + 1)% QUEUE_SIZE == paraQueuePtr->rear)
{
return true;
}
return false;
}
4、入队
//添加指向队列的指针
void enqueue(QueuePtr paraQueuePtr,BTNodePtr paraBTNodePtr)
{
printf("front = %d, rear = %d.rn",paraQueuePtr->front,paraQueuePtr->rear);
if((paraQueuePtr->front + 1)% QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE)
{
printf("错误,队列已满,无法加入%c.rn",paraBTNodePtr->element);
return;
}
paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr;
paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE;
printf("入队 %c,结束.rn",paraBTNodePtr->element);
}
5、出队
//从队列中移除一个元素并返回
BTNodePtr dequeue(QueuePtr paraQueuePtr)
{
if(isQueueEmpty(paraQueuePtr))
{
printf("错误,队列为空.rn");
return NULL;
}
paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE;
printf("出队 %c.rn",paraQueuePtr->nodePtrs[paraQueuePtr->front]->element);
return paraQueuePtr->nodePtrs[paraQueuePtr->front] ;
}
6、构造结点
//构造一个结点
BTNodePtr constructBTNode(char paraChar)
{
BTNodePtr resultPtr = (BTNodePtr)malloc(sizeof(BTNode));
resultPtr->element = paraChar;
resultPtr->left = NULL;
resultPtr->right = NULL;
return resultPtr;
}
7、核心函数将字符串构造二叉树
//使用给定的字符串构造二叉树
BTNodePtr stringToBTree(char* paraString)
{
int i;
char ch;
//使用队列管理指针
QueuePtr tempQueuePtr = initQueue();
BTNodePtr resultHeader;
BTNodePtr tempParent,tempLeft,tempRight;
i=0;
ch = paraString[i];
resultHeader = constructBTNode(ch);
enqueue(tempQueuePtr,resultHeader);
while(!isQueueEmpty(tempQueuePtr))
{
tempParent = dequeue(tempQueuePtr);
//左子树
i++;
ch = paraString[i] ;
if(ch == '#')
{
tempParent->left = NULL;
}
else
{
tempLeft = constructBTNode(ch);
enqueue(tempQueuePtr,tempLeft);
tempParent->left = tempLeft;
}
//右子树
i++;
ch = paraString[i] ;
if(ch == '#')
{
tempParent->right = NULL;
}
else
{
tempRight = constructBTNode(ch);
enqueue(tempQueuePtr,tempRight);
tempParent->right = tempRight;
}
}
return resultHeader;
}
8、4种遍历方式
//层序遍历
void levelwise(BTNodePtr paraTreePtr)
{
//使用队列管理指针
char tempString[100];
int i = 0;
QueuePtr tempQueuePtr = initQueue();
BTNodePtr tempNodePtr;
enqueue(tempQueuePtr,paraTreePtr);
while(!isQueueEmpty(tempQueuePtr))
{
tempNodePtr = dequeue(tempQueuePtr);
//输出
tempString[i] = tempNodePtr->element;
i++;
if(tempNodePtr->left != NULL)
{
enqueue(tempQueuePtr,tempNodePtr->left);
}
if(tempNodePtr->right != NULL)
{
enqueue(tempQueuePtr,tempNodePtr->right);
}
}
tempString[i] = ' ';
printf("层序遍历:%srn",tempString);
}
//前序遍历
void preorder(BTNodePtr tempPtr)
{
if(tempPtr == NULL);
{
return;
}
printf("%c",tempPtr->element);
preorder(tempPtr->left);
preorder(tempPtr->right);
}
//中序遍历
void inorder(BTNodePtr tempPtr)
{
if(tempPtr == NULL)
{
return ;
}
inorder(tempPtr->left);
printf("%c",tempPtr->element);
inorder(tempPtr->right);
}
//后序遍历
void postorder(BTNodePtr tempPtr)
{
if(tempPtr == NULL)
{
return ;
}
postorder(tempPtr->left);
postorder(tempPtr->right);
printf("%c",tempPtr->element);
}
总代码
#include#include #define QUEUE_SIZE 5 //二叉树结点 typedef struct BTNode { char element; BTNode* left; BTNode* right; } BTNode,*BTNodePtr; //带有多个指针的队列 typedef struct BTNodePtrQueue { BTNodePtr* nodePtrs; int front; int rear; } BTNodePtrQueue,*QueuePtr; //初始化队列 QueuePtr initQueue() { QueuePtr resultQueuePtr = (QueuePtr)malloc(sizeof(struct BTNodePtrQueue)); resultQueuePtr->nodePtrs = (BTNodePtr*)malloc(QUEUE_SIZE * sizeof(BTNodePtr)); resultQueuePtr->front = 0; resultQueuePtr->rear = 1; return resultQueuePtr; } //判断队列是否为空 bool isQueueEmpty(QueuePtr paraQueuePtr) { if((paraQueuePtr->front + 1)% QUEUE_SIZE == paraQueuePtr->rear) { return true; } return false; } //添加指向队列的指针 void enqueue(QueuePtr paraQueuePtr,BTNodePtr paraBTNodePtr) { printf("front = %d, rear = %d.rn",paraQueuePtr->front,paraQueuePtr->rear); if((paraQueuePtr->front + 1)% QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) { printf("错误,队列已满,无法加入%c.rn",paraBTNodePtr->element); return; } paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr; paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE; printf("入队 %c,结束.rn",paraBTNodePtr->element); } //从队列中移除一个元素并返回 BTNodePtr dequeue(QueuePtr paraQueuePtr) { if(isQueueEmpty(paraQueuePtr)) { printf("错误,队列为空.rn"); return NULL; } paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE; printf("出队 %c.rn",paraQueuePtr->nodePtrs[paraQueuePtr->front]->element); return paraQueuePtr->nodePtrs[paraQueuePtr->front] ; } //构造一个结点 BTNodePtr constructBTNode(char paraChar) { BTNodePtr resultPtr = (BTNodePtr)malloc(sizeof(BTNode)); resultPtr->element = paraChar; resultPtr->left = NULL; resultPtr->right = NULL; return resultPtr; } //使用给定的字符串构造二叉树 BTNodePtr stringToBTree(char* paraString) { int i; char ch; //使用队列管理指针 QueuePtr tempQueuePtr = initQueue(); BTNodePtr resultHeader; BTNodePtr tempParent,tempLeft,tempRight; i=0; ch = paraString[i]; resultHeader = constructBTNode(ch); enqueue(tempQueuePtr,resultHeader); while(!isQueueEmpty(tempQueuePtr)) { tempParent = dequeue(tempQueuePtr); //左子树 i++; ch = paraString[i] ; if(ch == '#') { tempParent->left = NULL; } else { tempLeft = constructBTNode(ch); enqueue(tempQueuePtr,tempLeft); tempParent->left = tempLeft; } //右子树 i++; ch = paraString[i] ; if(ch == '#') { tempParent->right = NULL; } else { tempRight = constructBTNode(ch); enqueue(tempQueuePtr,tempRight); tempParent->right = tempRight; } } return resultHeader; } //层序遍历 void levelwise(BTNodePtr paraTreePtr) { //使用队列管理指针 char tempString[100]; int i = 0; QueuePtr tempQueuePtr = initQueue(); BTNodePtr tempNodePtr; enqueue(tempQueuePtr,paraTreePtr); while(!isQueueEmpty(tempQueuePtr)) { tempNodePtr = dequeue(tempQueuePtr); //输出 tempString[i] = tempNodePtr->element; i++; if(tempNodePtr->left != NULL) { enqueue(tempQueuePtr,tempNodePtr->left); } if(tempNodePtr->right != NULL) { enqueue(tempQueuePtr,tempNodePtr->right); } } tempString[i] = ' '; printf("层序遍历:%srn",tempString); } //前序遍历 void preorder(BTNodePtr tempPtr) { if(tempPtr == NULL); { return; } printf("%c",tempPtr->element); preorder(tempPtr->left); preorder(tempPtr->right); } //中序遍历 void inorder(BTNodePtr tempPtr) { if(tempPtr == NULL) { return ; } inorder(tempPtr->left); printf("%c",tempPtr->element); inorder(tempPtr->right); } //后序遍历 void postorder(BTNodePtr tempPtr) { if(tempPtr == NULL) { return ; } postorder(tempPtr->left); postorder(tempPtr->right); printf("%c",tempPtr->element); } int main() { BTNodePtr tempHeader; tempHeader = constructBTNode('c'); printf("只有一个结点时,先序遍历:"); preorder(tempHeader); printf("rn"); char* tempString = "lty#yy#ds######"; tempHeader = stringToBTree(tempString); printf("先序遍历:"); preorder(tempHeader); printf("rn"); printf("中序遍历:"); inorder(tempHeader); printf("rn"); printf("后序遍历:"); postorder(tempHeader); printf("rn"); printf("层序遍历:"); levelwise(tempHeader); printf("rn"); return 1; }
结果展示
先序遍历: 中序遍历:tdyslyy 后序遍历:dsytyyl 层序遍历:front = 0, rear = 1. 入队 l,结束. 出队 l. front = 1, rear = 2. 入队 t,结束. front = 1, rear = 3. 入队 y,结束. 出队 t. front = 2, rear = 4. 入队 y,结束. 出队 y. front = 3, rear = 0. 入队 y,结束. 出队 y. front = 4, rear = 1. 入队 d,结束. front = 4, rear = 2. 入队 s,结束. 出队 y. 出队 d. 出队 s. 层序遍历:ltyyyds



