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

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

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

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

①若当前取得的元素为字母,则按如下规则建立一个新的(链)结点。
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

原文地址:https://www.cnblogs.com/codeloop/p/11783528.html

时间: 2024-11-04 22:47:00

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

二叉树各种相关操作(建立二叉树、前序、中序、后序、求二叉树的深度、查找二叉树节点,层次遍历二叉树等)(C语言版)

将二叉树相关的操作集中在一个实例里,有助于理解有关二叉树的相关操作: 1.定义树的结构体: 1 typedef struct TreeNode{ 2 int data; 3 struct TreeNode *left; 4 struct TreeNode *right; 5 }TreeNode; 2.创建根节点: 1 TreeNode *creatRoot(){ 2 TreeNode * root =(TreeNode *)malloc(sizeof(TreeNode)); 3 if(NULL=

二叉树的创建和四种遍历(前序、先序、后序、层次、结点的层数、深度、叶子数等)—java描述

二叉树的创建和四种遍历(前序.先序.后序.层次.结点的层数.深度.叶子数等)—java描述 package javab; //树的结点类 public class TreeNode { String data; TreeNode leftChild,rightChild,next; public TreeNode(String data){ this.data=data; } public TreeNode(String data,TreeNode left,TreeNode right){ l

二叉树 的先序 中序、后序遍历、层次遍历以及树状打印等操作

#include <stdio.h> #include <stdlib.h> #define MAXSIZE 50 typedef struct Node { char data; struct Node *LChild; struct Node *RChild; }BiTNode,*BiTree; typedef struct { BiTree element[MAXSIZE]; int front; int rear; }SeqQueue; /*初始化队列*/ void Ini

二叉树和广义表的转换

1 //广义表转二叉树: 2 设置一个标记变量k,初始值为-1: 3 设置一个标记结点p: 4 循环遍历广义表的字符串str: 5 如果str[i]是左括号: 6 则设置k为0: 7 把p压入栈中. 8 否则如果str[i]是逗号: 9 则设置k为1. 10 否则如果str[i]是右括号: 11 则栈顶元素出栈. 12 否则如果str[i]是一个字母,用结点temp来存储: 13 如果k为-1: 14 则把temp作为根结点并压入栈中. 15 如果k为0: 16 如果此时栈顶结点是p,则先出栈:

Java实现二叉树先序,中序,后序遍历

以下是我要解析的一个二叉树的模型形状 接下来废话不多直接上代码 一种是用递归的方法,另一种是用堆栈的方法: 首先创建一棵树: 节点对象: 1 public class Node { 2 //节点数值 3 private int data; 4 //左子节点 5 private Node leftNode; 6 //右子节点 7 private Node rightNode; 8 9 public Node(int data, Node leftNode, Node rightNode) { 10

数据结构-二叉树(1)以及前序、中序、后序遍历(python实现)

上篇文章我们介绍了树的概念,今天我们来介绍一种特殊的树--二叉树,二叉树的应用很广,有很多特性.今天我们一一来为大家介绍. 二叉树 顾名思义,二叉树就是只有两个节点的树,两个节点分别为左节点和右节点,特别强调,即使只有一个子节点也要区分它是左节点还是右节点. 常见的二叉树有一般二叉树.完全二叉树.满二叉树.线索二叉树.霍夫曼树.二叉排序树.平衡二叉树.红黑树.B树这么多种类.我们这篇文章中简单介绍一般二叉树.完全二叉树和满二叉树. 一般二叉树 很简单,只要满足子节点数不超过两个的树就是一棵二叉树

PTA 二叉树的三种遍历(先序、中序和后序)

6-5 二叉树的三种遍历(先序.中序和后序) (6 分) 本题要求实现给定的二叉树的三种遍历. 函数接口定义: void Preorder(BiTree T); void Inorder(BiTree T); void Postorder(BiTree T); T是二叉树树根指针,Preorder.Inorder和Postorder分别输出给定二叉树的先序.中序和后序遍历序列,格式为一个空格跟着一个字符. 其中BinTree结构定义如下: typedef char ElemType; typed

中序与后序或者前序都可以确定一颗二叉树 一点点dfs

中序与后序或者前序都可以确定一颗二叉树原理:  中序是 访问顺序是左子树 根 右子树 后续是 左子树 右子树 根 所以一棵二叉树如果给了后续的信息 可以把树根确定下来 带入中序的信息中 找出左右子树 再带回后续的信息找这样反复,也就是递归下去,可以把树给确定下来. DFS  大概可以用于 又要向下延伸 又要左右延伸  比如 枚举 ,搜索 都可以用:

【基础备忘】 二叉树前序、中序、后序遍历相互求法

转自:http://www.cnblogs.com/fzhe/archive/2013/01/07/2849040.html 今天来总结下二叉树前序.中序.后序遍历相互求法,即如果知道两个的遍历,如何求第三种遍历方法,比较笨的方法是画出来二叉树,然后根据各种遍历不同的特性来求,也可以编程求出,下面我们分别说明. 首先,我们看看前序.中序.后序遍历的特性: 前序遍历:     1.访问根节点     2.前序遍历左子树     3.前序遍历右子树 中序遍历:     1.中序遍历左子树     2