二叉树的广义表创建及中序遍历、后序遍历、层次遍历的非递归算法(C语言)

北战南征 提交于 2019-12-03 07:40:14

广义表创建二叉树
关于用广义表的形式表示二叉树的形式如下

①广义表中的一个字母代表一个结点的数据信息。
②每个根结点作为由子树构成的表的名字放在义表的前面。
③每个结点的左子树与右子树之间用逗号分开。若结点只有右子树面无左子树,则该逗号不能省略。
④在整个广义表的末尾加一个特殊符号(如“@”)作为结束标志。

下面先用自然语言描述算法如下。
依次从广义表中取得-个元素,并对取得的元素做如下相应的处理。

①若当前取得的元素为字母,则按如下规则建立一个新的(链)结点。
a)若该结点为二叉树的根结点,则将该结点的地址送T。
b)若该结点不是二叉树的根结点,则将该结点作为左孩子(若标志flag为1)或者右子若标志flag为2)链接到其双亲结点上(此时双亲结点的地址在栈顶位置)。

②若当前取得的元素为左括号“(”,则表明一个子表开始,将标志flag置为1,同时将面那个结点的地址进栈。

③若当前取得的元素为右括号“)”,则表明一个子表结束,做退栈操作。

④若当前取得的元素为逗号,则表明以左孩子为根的子树处理完毕,接着应该处理孩子为根的子树,将标志flag置为2。

如此处理广义表中的每一个元素,直到取得广义表的结束符号“@”为止。

二叉树的中序遍历(非递归)
算法的核心思想是:
当P所指的结点不为空时.则将该结点所在链结点的地址进栈,然后再将”指向该结点的左孩子结点:当P所指的结点为空时则从堆栈中退出栈项元素(某个结宜的地址)送p.并访问该结点,然后再将p指向该结点的右孩子结点。重复上述过程,直到P为NULL.并且堆栈也为空,遍历结束。

二叉树的后序遍历(非递归)
下面再讨论后序遍历的非递归算法:

在对二又树进行后序遍历的过程中,当指针p指向某一个结点时,不能马上对它进行访问,而要先遍历它的左子树,因而要将此结点的地址进栈;当其左子树遍历完毕之后,再次搜索到该结点时(该结点的地址通过退栈得到),还不能对它进行访问,还需要遍历它的右子树,所以,再一次将此结点的地址进栈。只有当该结点的右子树被遍历后回到该结点,才访问该结点。为了标明某结点是否可以被访问,引人一个标志变量flag,
并有
1、flag=0表示该结点暂不访问
2、flag =1表示该结点可以访问
标志flag的值随同进栈结点的地址起进栈和出栈。因此,算法中设置了两个空间足够的堆栈,其中,STACK1[0… M- 1 ]存放进栈结点的地址,STACK2[0… M- 1]存放相应的标志flag的值,两个堆栈使用同一栈顶指针top,top的初值为一1。

二叉树的按层次遍历
下面测试的算法中使用了一个顺序存储结构队列QUEUE[0. . M- 1],(不妨假设队列的空间足够大).front与rear分别为队头指针和队尾指针。遍历进行之前先把二叉树根结点的存储地址进队.然后依次从队列中退出一个元素(结点的存储地址);每退出一个元素,先访问该元素所指的结点.然后依次把该结点的左孩子结点(若存在的话)与右孩子结点(若存在的话)的地址依次进队。如此重复下去,直到队列为空。此时,访问结点的次序就是按层次遍历该二叉树的次序。

有关中序遍历,后序遍历,层次遍历的非递归算法和二叉树的广义表创建一起测试

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #define M 100
  4 
  5 typedef struct BTREE {
  6 char data;
  7 struct BTREE *lchild, *rchild;
  8 }BT, *LBTREE;
  9 
 10 LBTREE Creat()
 11 {
 12 LBTREE STACK[M], p = NULL, T = NULL;
 13 int flag, top = -1;
 14 char ch;
 15 while (1)
 16 {
 17 scanf_s("%c", &ch);
 18 switch (ch)
 19 {
 20 case '(':    //左括号则下一个读取字符入栈
 21 STACK[++top] = p;
 22 flag = 1;
 23 break;
 24 case ')':    //右括号则栈顶元素出栈
 25 top--;
 26 break;
 27 case ',':
 28 flag = 2;
 29 break;
 30 case '@':    //返回T,表示创建完毕
 31 return T;
 32 default:    //读到字母时
 33 p = (LBTREE)malloc(sizeof(BT));
 34 p->data = ch;
 35 p->lchild = NULL;
 36 p->rchild = NULL;
 37 if (T == NULL)
 38 T = p;
 39 else if (flag == 1)
 40 STACK[top]->lchild = p;
 41 else if (flag == 2)
 42 STACK[top]->rchild = p;
 43 }
 44 }
 45 }
 46 
 47 void INORDER(LBTREE T)    //中序遍历非递归
 48 {
 49 LBTREE STACK[M], p = T;
 50 int top = -1;
 51 if (T != NULL)
 52 {
 53 do {
 54 while (p != NULL)    //这里不可以是 (p=p->lchild)!=NULL
 55 {
 56 STACK[++top] = p;
 57 p = p->lchild;
 58 }
 59 p = STACK[top--];    //出栈
 60 printf("%c", STACK[top + 1]->data);
 61 p = p->rchild;
 62 } while (!(p == NULL && top == -1));
 63 }
 64 }
 65 
 66 void LAYERORDER(LBTREE T)    //按层次遍历
 67 {
 68 LBTREE QUEUE[M], p;
 69 int front, rear;
 70 if (T != NULL)    //队列
 71 {
 72 QUEUE[0] = T;
 73 front = -1;
 74 rear = 0;
 75 while (front < rear)
 76 {
 77 p = QUEUE[++front];
 78 printf("% c", p->data);
 79 if (p->lchild != NULL)
 80 QUEUE[++rear] = p->lchild;
 81 if (p->rchild != NULL)
 82 QUEUE[++rear] = p->rchild;
 83 
 84 }
 85 }
 86 }
 87 
 88 void POSTORED(LBTREE T)    //后序遍历的非递归算法
 89 {
 90 LBTREE STACK1[M];    //创建了两个栈,一个用来存放结点的地址
 91 int STACK2[M], flag, top = -1;    //另一个用来存放数字,1:可以读取,0:不可读取
 92 LBTREE p = T;
 93 if (T != NULL)
 94 {
 95 do {
 96 while (p != NULL)
 97 {
 98 STACK1[++top] = p;
 99 STACK2[top] = 0;
100 p = p->lchild;
101 }
102 p = STACK1[top];
103 flag = STACK2[top--];
104 if (flag == 0)
105 {
106 STACK1[++top] = p;
107 STACK2[top] = 1;
108 p = p->rchild;
109 }
110 else
111 {
112 printf("%c", p->data);
113 p = NULL;
114 }
115 } while (!(p == NULL && top == -1));
116 }
117 }
118 
119 
120 void Distroyb(LBTREE T)    //销毁二叉树(同样使用递归的方式)
121 {
122 if (T != NULL)
123 {
124 Distroyb(T->lchild);
125 Distroyb(T->rchild);
126 free(T);
127 }
128 }
129 
130 
131 void main(void)
132 {
133 LBTREE T = NULL;
134 puts("输入二叉树数据");    
135 T=Creat(T);
136 
137 puts("按层次遍历输出:");
138 LAYERORDER(T);
139 puts("");
140 
141 puts("非递归中序遍历:");
142 INORDER(T);
143 puts("");
144 
145 puts("非递归后续遍历:");
146 POSTORED(T);
147 
148 Distroyb(T);    //销毁二叉树
149 }

 

输入:
A(B(D,E(G)),C(F(,H)))@
以下是结果:

 

 

嗝~
codeloop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!