一、二叉树的定义与基本操作
定义:把满足以下两个条件的树型结构叫做二叉树(Binary Tree):
(1) 每个结点的度都不大于 2;
(2) 每个结点的孩子结点次序不能任意颠倒。
由此定义可看出,一个二叉树中的每个结点只能含有 0、1 或 2 个孩子,而且每个孩子有左右之分。位于左边的孩子叫做左孩子,位于右边的孩子叫做右孩子。
代码:
#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; }//Of initQueue bool isQueueEmpty(QueuePtr paraQueuePtr){ if ((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear) { return true; }//Of if return false; }//Of isQueueEmpty 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; }//Of if paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr; paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE; printf("enqueue %c ends.rn", paraBTNodePtr->element); }//Of enqueue BTNodePtr dequeue(QueuePtr paraQueuePtr){ if (isQueueEmpty(paraQueuePtr)) { printf("Error, empty queuern"); return NULL; }//Of if paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE; //BTNodePtr tempPtr = paraQueuePtr->nodePtrs[paraQueuePtr->front + 1]; printf("dequeue %c ends.rn", paraQueuePtr->nodePtrs[paraQueuePtr->front]->element); return paraQueuePtr->nodePtrs[paraQueuePtr->front]; }//Of dequeue BTNodePtr constructBTNode(char paraChar){ BTNodePtr resultPtr = (BTNodePtr)malloc(sizeof(BTNode)); resultPtr->element = paraChar; resultPtr->left = NULL; resultPtr->right = NULL; return resultPtr; }//Of constructBTNode BTNodePtr stringToBTree(char* paraString){ int i; char ch; //Use a queue to manage the pointers 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; }//Of if //The right child i ++; ch = paraString[i]; if (ch == '#') { tempParent->right = NULL; } else { tempRightChild = constructBTNode(ch); enqueue(tempQueuePtr, tempRightChild); tempParent->right = tempRightChild; }//Of if }//Of while return resultHeader; }//Of stringToBTree void levelwise(BTNodePtr paraTreePtr){ //Use a queue to manage the pointers char tempString[100]; int i = 0; QueuePtr tempQueuePtr = initQueue(); BTNodePtr tempNodePtr; enqueue(tempQueuePtr, paraTreePtr); while(!isQueueEmpty(tempQueuePtr)) { tempNodePtr = dequeue(tempQueuePtr); //For output. tempString[i] = tempNodePtr->element; i ++; if (tempNodePtr->left != NULL){ enqueue(tempQueuePtr, tempNodePtr->left); }//Of if if (tempNodePtr->right != NULL){ enqueue(tempQueuePtr, tempNodePtr->right); }//Of if }//Of while tempString[i] = ' '; printf("Levelwise: %srn", tempString); }//Of levelwise void preorder(BTNodePtr tempPtr){ if (tempPtr == NULL){ return; }//Of if printf("%c", tempPtr->element); preorder(tempPtr->left); preorder(tempPtr->right); }//Of preorder void inorder(BTNodePtr tempPtr){ if (tempPtr == NULL) { return; }//Of if inorder(tempPtr->left); printf("%c", tempPtr->element); inorder(tempPtr->right); }//Of inorder void postorder(BTNodePtr tempPtr){ if (tempPtr == NULL) { return; }//Of if postorder(tempPtr->left); postorder(tempPtr->right); printf("%c", tempPtr->element); }//Of postorder 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; }//Of main
运行结果:
二叉树的性质
1:在二叉树的第i层上最多有2^(i-1)个节点
2:深度为K的二叉树之多有2^(k-1)个节点
注:这里的深度K意思就是有K层的二叉树
3:对于任何一棵二叉树T,如果其终端节点有No个,度为2的节点数有N2,则No=N2+1
4: 具有n个节点的完全二叉树的深度为[log2n]+1([x]表示不大于x的最大整数)
满二叉树:深度为 k 且有 2k-1 个结点的二叉树。在满二叉树中,每层结点都是满的, 即每层结点都具有最大结点数。如下图(a)所示的二叉树即为一棵满二叉树。
满二叉树的顺序表示,即从二叉树的根开始,层间从上到下,层内从左到右,逐层进行 编号(1,2,··· ,n)。例如下图(a)所示的满二叉树的顺序表示为(1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15)。
完全二叉树:深度为 k,结点数为 n 的二叉树,如果其结点 1~n 的位置序号分别与满 二叉树的结点 1~n 的位置序号一一对应,则为完全二叉树,如下图(b)所示。 可见,满二叉树必为完全二叉树,而完全二叉树不一定是满二叉树。



