二叉树
定义:
-
每个结点的度不能大于2;
-
每个节点的孩子结点次序不能任意颠倒;
性质:
-
在二叉树的第
i
层上至多有2i-1个结点; -
深度为K的二叉树至多有2i-1个结点;
-
任意一棵二叉树T,若终端结点数为n0,而其度数为2的结点数为n2,则 n0 = n2+1
-
具有n个结点的完全二叉树的深度 long2n(向下取整) +1
存储结构(链表)
//二叉链表结点结构; typedef struct Node{ DataType data; struct Node *LChild; struct Node *RChild; }BiTNode,*BiTree;
1.建立二叉链表方式存储的二叉树(扩展二叉树**空结点用"."来表示**)
-
参数采用二级指针(才可在自定义函数内返回创建的结点,创建出树)
//扩展先序遍历序列创建二叉链表; void CreateBiTree(BiTree *bt){ //参数为二级指针(*bt); char ch; ch=getchar(); //一次性输入,逐个输入(回车也当为一个字符); if(ch == '.' ){ *bt=NULL; } else { *bt = (BiTree) malloc (sizeof (BiTNode)); //动态开辟二叉结点; (*bt)->data = ch; CreateBiTree(&(*bt)->Lchild); //递归调用左子树; CreateBiTree(&(*bt)->Rchild); //递归调用右子树; } }
线索二叉树
定义
-
二叉树的遍历运算是将二叉树中结点按一定规律线性化的过程。
-
有n个结点的二叉链表中共有2n个链域,但有n+1个空指针域,利用这n+1个空指针域建立线索(相应的前后继结点)。
//线索二叉树的结点结构; typedef struct Node { ThreadType data; struct Node *LChild,*RCild; int Ltag,Rtag; //标志位,标志位=0表示存在左或右孩子,否则建立相应的前驱或后继结点; }BiTNode,*BiTree;
-
算法步骤:
-
建立一个二叉树(创建的同时给标志位Ltag、Rtag赋初值);
-
中序遍历二叉树的同时建立中序线索树;
1.设置两个指针(p,pre)分别存放当前结点和此结点的前驱结点;
2.中序遍历的时建立相应结点的前驱结点和后继结点;
-
//建立中序线索树; void Inthread(BiTree p){ //建立在中序遍历二叉树的基础之上; static BiTree pre = NULL; //设置静态变量pre; if (p == NULL){ return; } Inthread (p->LChild); //遍历左子树; if(p->LChild == NULL ){ //建立p的前驱线索; p->Ltag = 1; p->LChild = pre; } if ( pre!= NULL&&pre->RChild==NULL ){ //置后继线索,pre!=NULL,开始时判断以防止程序错误; pre->Rtag = 1; pre->RChild = p; } pre = p; //当前访问结点为下一个访问结点的前驱; Inthread(p->RChild); } //在中序线索树中找结点的后继; BiTree InNext (BiTree p){ static BiTree q = NULL; if (p->Rtag==1) { //标志位为1,可直接找到后继结点; q = p->RChild; } else { //右标志为0,则要找到右子树最左下角的结点; q = p->RChild; while (q->Ltag==0){ //查找最左下角的结点; q = q->LChild; } } return q; } //在中序线索树中找结点的前驱; BiTree INpre (BiTree p){ static BiTree q = NULL; if (p->Ltag == 1){ //标志位为1,可直接找到前驱结点; q = p->LChild; } else { //坐标志位0,则要找到左子树最右下角的结点; q = p->LChild; while (q->Ltag == 0){ //查找最左下角的结点; q = q->RChild; } } return q; } //中序遍历线索二叉树; void ThreadOrder(BiTree bt){ BiTNode *p; if (bt == NULL) return; p = bt; while (p->Ltag == 0){ //查找中序遍历的第一个结点p; p = p->LChild; } printf("%d",p->data); //访问第一个结点; while (p->RChild !=NULL){ //当p存在后继,依次访问后继节点; p = InNext(p); printf("%d",p->data); } }