(1) 二叉树的前序遍历程序,包含递归、非递归。
(2) 二叉树的中序遍历程序,包含递归、非递归。
(3) 二叉树的后序遍历程序,包含递归、非递归。
代码如下
#include <stdio.h>
#include <stdlib.h>
// 定义节点
typedef struct Node {
char data;
struct Node* lChild;
struct Node* rChild;
} BinTNode;
// 根据广义表表示二叉树结构来创建二叉树链表
BinTNode* createTree(char *str) {
// 用指针数组st存放双亲节点
BinTNode *st[100];
// 用来一生成节点时用的
BinTNode *p = NULL;
// 二叉树链表的头节点
BinTNode *b = NULL;
// top用来记录st的栈顶,key用来记录下一个节点是当前节点的左子树(用1表示)还是右子树(用2表示),j是用来遍历str字符串用的
int top = -1, key, j = 0;
// 取得第一个字符
char ch = str[j];
// 当字符串没有结束,就继续循环,'\0'是字符串的结束标记
while (ch != '\0') {
// 在遍历广义表表示二叉树结构过程中,会遇到'(',',',')'和字母
switch (ch) {
// 遇到'(',就是左子树,将key标记为1,以作记录,将当前节点记录到栈st中
case '(':
top++;
st[top] = p;
key = 1;
break;
// 遇到',',就是右子树,将key标记为1,以作记录
case ',':
key = 2;
break;
// 遇到')',说明此子树已遍历完成,要返回到上一个双亲节点,准备遍历双亲节点的另一棵子树
case ')':
top--;
break;
// 遇到节点,为节点申请内存,并初始化节点
default:
p = (BinTNode*)malloc(sizeof(BinTNode));
p->data = ch;
p->lChild = p->rChild = NULL;
// 记录头结点
if (b == NULL) {
b = p;
}
else {
// 如果是非头结点,那么就根据key的值,将节点添加到双亲节点的子树上去
switch (key) {
case 1:
st[top]->lChild = p;
break;
case 2:
st[top]->rChild = p;
break;
}
}
}
// 遍历下一个字符
j++;
ch = str[j];
}
// 返回头结点
return b;
}
void preOrder(Node* root)
{
Node* stack[100], *curr;
int top, end;
if (root == NULL)
return;
top = end = 0;
//根结点入栈
stack[top++] = root;
while (top > 0)
{
//取栈顶
curr = stack[--top];
printf("%c ", curr->data);
//右子树入栈
if (curr->rChild)
stack[top++] = curr->rChild;
//左子树入栈
if (curr->lChild)
stack[top++] = curr->lChild;
//访问节点
}
printf("\n");
return;
}
//中序遍历,非递归
void inorder(Node *root)
{
Node *stack[1000], *curr;
int top, end;
if (root == NULL)
return;
top = end = 0;
//根结点进栈
stack[top++] = root;
//当前节点指向左孩子
curr = root->lChild;
while (curr || top > 0)
{
//节点存在,则父节点进栈,指向左孩子
if (curr)
{
if (curr->lChild)
{
stack[top++] = curr;
curr = curr->lChild;
continue;
}
}
else
{
curr = stack[--top];
}
//取栈顶,访问后,指向右孩子
printf("%c ", curr->data);
curr = curr->rChild;
}
printf("\n");
return;
}
//后序遍历,非递归
void postOrder(Node* root)
{
Node* stack[1000], *curr,*prev=NULL;
int top, end;
if (root == NULL)
return;
top = end = 0;
//根结点入栈
stack[top++] = root;
//指向左孩子
curr = root->lChild;
while (curr || top > 0)
{
//只要存在孩子节点,则父节点进栈,指向其孩子节点。
if (curr)
{
if (curr->lChild|| curr->rChild)
{
stack[top++] = curr;
if (curr->lChild)
curr = curr->lChild;
else
curr = curr->rChild;
continue;
}
}
else
{
//取栈顶,如果存在右孩子且和上一个访问节点不一样,则父节点
//继续进栈,指向右孩子。
curr = stack[--top];
if (curr->rChild && curr->rChild != prev)
{
stack[top++] = curr;
curr = curr->rChild;
continue;
}
}
//访问节点同时保存访问的位置。
printf("%c ", curr->data);
prev = curr;
curr = NULL;
}
printf("\n");
return;
}
//前序递归遍历
void preTraverse(Node* T)
{
if (T)
{
printf("%c ",T->data);
preTraverse(T->lChild);
preTraverse(T->rChild);
}
}
//中序递归遍历
void midTraverse(Node *T)
{
if (T)
{
midTraverse(T->lChild);
printf("%c ", T->data);
midTraverse(T->rChild);
}
}
//后序递归遍历
void postTraverse(Node* T)
{
if (T)
{
postTraverse(T->lChild);
postTraverse(T->rChild);
printf("%c ", T->data);
}
}
int main() {
char str[] = "(a(b(,d(e,f)),c))";
Node* tree = createTree(str);
printf("前序非递归遍历为\n");
preOrder(tree);
printf("中序非递归遍历为\n");
inorder(tree);
printf("后序非递归遍历为\n");
postOrder(tree);
printf("前序递归遍历为\n");
preTraverse(tree);
printf("\n");
printf("中序递归遍历为\n");
midTraverse(tree);
printf("\n");
printf("后序递归遍历为\n");
postTraverse(tree);
return 0;
}
运行截图如下