二叉树是n(n≥0)个结点所构成的集合,它或为空树(n=0),或为非空树,非空树是由一个根(root)以及两个不相交的元素,被称为左子树(Left child)和右子树(Right child)的二叉树组成的。如图:
代码实现:
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;
}
进队:
void enqueue(QueuePtr paraQueuePtr, BTNodePtr paraBTNodePtr){
printf("front = %d, rear = %d.rn", paraQueuePtr->front, paraQueuePtr->rear);
// 判断队列是否已满
if ((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) {
printf("Error, trying to enqueue %c. queue full.rn", paraBTNodePtr->element);
return;
}
paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr;
paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE;
printf("enqueue %c ends.rn", paraBTNodePtr->element);
}
出队:
BTNodePtr dequeue(QueuePtr paraQueuePtr){
if (isQueueEmpty(paraQueuePtr)) {
printf("Error, empty queuern");
return NULL;
}
paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE;
printf("dequeue %c ends.rn", paraQueuePtr->nodePtrs[paraQueuePtr->front]->element);
return paraQueuePtr->nodePtrs[paraQueuePtr->front];
}
将有序字符串存入二叉树:
BTNodePtr stringToBTree(char* paraString){
int i;
char ch;
//用一个队列来管理指针
QueuePtr tempQueuePtr = initQueue();
BTNodePtr resultHeader;
BTNodePtr tempParent, tempLeftChild, tempRightChild;
i = 0;
ch = paraString[i];
resultHeader = constructBTNode(ch);
enqueue(tempQueuePtr, resultHeader);
while(!isQueueEmpty(tempQueuePtr)) { // 判断队列是否为空
tempParent = dequeue(tempQueuePtr);
//The left child
i ++;
ch = paraString[i];
if (ch == '#') {
tempParent->left = NULL;
} else {
tempLeftChild = constructBTNode(ch);
enqueue(tempQueuePtr, tempLeftChild);
tempParent->left = tempLeftChild;
}
//The right child
i ++;
ch = paraString[i];
if (ch == '#') {
tempParent->right = NULL;
} else {
tempRightChild = constructBTNode(ch);
enqueue(tempQueuePtr, tempRightChild);
tempParent->right = tempRightChild;
}
}
return resultHeader;
}
三、四种遍历
二叉树的遍历有四种方式:前序遍历、中序遍历、后序遍历、层序遍历
其中前、中、后序遍历均用到了递归的方法,而层序遍历用了队列的方式实现
遍历演示以下面该图为准
1、前序遍历
先访问根节点,再前序遍历左右两棵子树。结果是:ABDECFG
void preorder(BTNodePtr tempPtr){
if (tempPtr == NULL){
return;
}
printf("%c", tempPtr->element);
preorder(tempPtr->left);
preorder(tempPtr->right);
2、中序遍历
先中序遍历左子树,然后访问根节点,最后中序遍历右子树。结果是:DBEAFCG
void inorder(BTNodePtr tempPtr){
if (tempPtr == NULL) {
return;
}
inorder(tempPtr->left);
printf("%c", tempPtr->element);
inorder(tempPtr->right);
}
这里遍历有个技巧,可以把该二叉树投影在一条水平直线上,从左往右就是中序遍历的结果,如图
3、后序遍历
先后序遍历左子树,再后序遍历右子树,最后访问根节点。后序遍历的结果是:DEBFGCA
void postorder(BTNodePtr tempPtr){
if (tempPtr == NULL) {
return;
}
postorder(tempPtr->left);
postorder(tempPtr->right);
printf("%c", tempPtr->element);
}
4、层序遍历
从根节点开始,逐层访问各子节点。层序遍历的结果是:ABCDEFG
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("Levelwise: %srn", tempString);
}
四、总代码
#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->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) { printf("Error, trying to enqueue %c. queue full.rn", paraBTNodePtr->element); return; } paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr; paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE; printf("enqueue %c ends.rn", paraBTNodePtr->element); } BTNodePtr dequeue(QueuePtr paraQueuePtr){ if (isQueueEmpty(paraQueuePtr)) { printf("Error, empty queuern"); return NULL; } paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE; printf("dequeue %c ends.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, tempLeftChild, tempRightChild; i = 0; ch = paraString[i]; resultHeader = constructBTNode(ch); enqueue(tempQueuePtr, resultHeader); while(!isQueueEmpty(tempQueuePtr)) { tempParent = dequeue(tempQueuePtr); //The left child i ++; ch = paraString[i]; if (ch == '#') { tempParent->left = NULL; } else { tempLeftChild = constructBTNode(ch); enqueue(tempQueuePtr, tempLeftChild); tempParent->left = tempLeftChild; } //The right child i ++; ch = paraString[i]; if (ch == '#') { tempParent->right = NULL; } else { tempRightChild = constructBTNode(ch); enqueue(tempQueuePtr, tempRightChild); tempParent->right = tempRightChild; } } 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("Levelwise: %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("There is only one node. Preorder visit: "); preorder(tempHeader); printf("rn"); char* tempString = "acde#bf######"; tempHeader = stringToBTree(tempString); printf("Preorder: "); preorder(tempHeader); printf("rn"); printf("Inorder: "); inorder(tempHeader); printf("rn"); printf("Postorder: "); postorder(tempHeader); printf("rn"); printf("Levelwise: "); levelwise(tempHeader); printf("rn"); return 1; }



