一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
二叉树的特点:
- 每个结点最多有两棵子树,即二叉树不存在度大于2的结点。
- 二叉树的子树有左右之分,其子树的次序不能颠倒。
二叉树一般可以使用两种存储结构,一种顺序结构,一种链式结构。
二叉树的性质-
若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1) 个结点.
-
若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2^h- 1.
-
对任何一棵二叉树, 如果度为0其叶结点个数为 n0, 度为2的分支结点个数为 n2,则有n0=n2+1
-
若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=Log2(n+1). (ps:Log2(n+1)是log以2为
底,n+1为对数)
下面是老师的代码
#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
运行结果
There is only one node. Preorder visit: c front = 0, rear = 1. enqueue a ends. dequeue a ends. front = 1, rear = 2. enqueue c ends. front = 1, rear = 3. enqueue d ends. dequeue c ends. front = 2, rear = 4. enqueue e ends. dequeue d ends. front = 3, rear = 0. enqueue b ends. front = 3, rear = 1. enqueue f ends. dequeue e ends. dequeue b ends. dequeue f ends. Preorder: acedbf Inorder: ecabdf Postorder: ecbfda Levelwise: front = 0, rear = 1. enqueue a ends. dequeue a ends. front = 1, rear = 2. enqueue c ends. front = 1, rear = 3. enqueue d ends. dequeue c ends. front = 2, rear = 4. enqueue e ends. dequeue d ends. front = 3, rear = 0. enqueue b ends. front = 3, rear = 1. enqueue f ends. dequeue e ends. dequeue b ends. dequeue f ends. Levelwise: acdebf Press any key to continue
我的代码
#includeusing namespace std; //定义节点 typedef struct node { struct node *lchild; struct node *rchild; char data; }BiTreeNode, *BiTree; //*BiTree的意思是给 struct node*起了个别名,叫BiTree,故BiTree为指向节点的指针。 //按照前序顺序建立二叉树 void createBiTree(BiTree &T) //&的意思是传进来节点指针的引用,括号内等价于 BiTreeNode* &T,目的是让传递进来的指针发生改变 { char c; cin >> c; if('#' == c) //当遇到#时,令树的根节点为NULL,从而结束该分支的递归 T = NULL; else { T = new BiTreeNode; T->data=c; createBiTree(T->lchild); createBiTree(T->rchild); } } //前序遍历二叉树并打印 void preTraverse(BiTree T) { if(T) { cout< data<<" "; preTraverse(T->lchild); preTraverse(T->rchild); } } //中序遍历二叉树并打印 void midTraverse(BiTree T) { if(T) { midTraverse(T->lchild); cout< data<<" "; midTraverse(T->rchild); } } //后续遍历二叉树并打印 void postTraverse(BiTree T) { if(T) { postTraverse(T->lchild); postTraverse(T->rchild); cout< data<<" "; } } int main() { BiTree T; //声明一个指向二叉树根节点的指针 createBiTree(T); cout<<"二叉树创建完成!"< 总结 二叉树的建立采用的是递归的思想:给定一个指向根节点的指针,然后递归调用ceate()函数,自动生成一个二叉树。就像是在地上挖了个坑(根节点),然后他会拿着铲子(create函数)按照一定的规则自动挖一个很大的洞穴(二叉树)出来。当然挖坑前需要先定义每个洞长什么样(定义节点结构)。
二叉树的遍历采用的也是递归的思想:如果节点有数据,则按照遍历规则打印根节点和孩子节点,没有数据则返回直到所有数据都遍历完,递归结束。



