结果如下图:
#号代表NULL,此时没有节点
一、在c语言中进行二叉树的非递归遍历需要用到栈,而在c语言中没有直接调用栈的接口,所以在实现非递归遍历时需要先实现一个栈,需要用到出栈,入栈,栈顶元素,判断栈是否为空,这四个接口,别的可以不用实现。
二、 实现栈的接口
注意:这里栈的数组需要用到的类型时Node 类型的,所以先把二叉树节点Node定义出来才能才能使用Node这个类型
typedef struct Node//定义树的一个节点
{struct Node *_left;struct Node *_right;BDataType _data;
}Node;
进行栈的接口实现
typedef Node* SDataType;
typedef struct stack//定义栈
{SDataType *_array;int _count;//总容量大小int _size;//当前元素大小
}stack;
void stackInit(stack *st)//栈的初始化
{st->_array = (SDataType*)malloc(sizeof(SDataType)*num);st->_count = num;st->_size = 0;
}
void stackInsert(stack *st, SDataType value)//入栈
{if (st->_size == st->_count)//空间已满,需要扩容{st->_array = (SDataType*)realloc(st->_array, sizeof(SDataType)*(2 * st->_count));st->_count = 2 * st->_count;}st->_array[st->_size] = value;st->_size++;
}
void stackDel(stack *st)//出栈
{if (st->_size == 0){printf("栈以为空,不能出栈!!!\n");}st->_size--;
}SDataType stackTop(stack *st)//获取栈顶元素
{return st->_array[st->_size - 1];
}
int stackEmpty(stack *st)//判断栈是否为空
{if (st->_size == 0){return 1;}return 0;
}
三、创建一棵树
可以用前序遍历去创建一棵树
这里的#号是代表NULL的,不太懂怎样建树的可以先把牛客上的一道题做完之后就会用各种方法去建树了,
链接在这:https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId=60&&tqId=29483&rp=1&ru=/activity/oj&qru=/ta/tsing-kaoyan/question-ranking
Node *TreeCreat(BDataType *array, int *pos)//创建一棵树,后面会对这棵树进行各种排序
{if (array[*pos] != '#'){Node *root = (Node *)malloc(sizeof(Node));root->_data = array[*pos];(*pos)++;root->_left = TreeCreat(array, pos);(*pos)++;root->_right = TreeCreat(array, pos);return root;}else{return NULL;}
}
四、非递归去实现三种遍历
1、前序遍历
先遍历当前节点的最左路径,再遍历最后访问节点的右子树
void preOrder(Node *root)//前序遍历非递归
{printf("前序遍历#: ");stack st;stackInit(&st);Node *cur = root;Node *top;while (cur || stackEmpty(&st) != 1){//从当前根的位置,一直遍历完最左路径while (cur){printf("%c ", cur->_data);stackInsert(&st, cur);cur = cur->_left;}//获取栈顶元素top = stackTop(&st);stackDel(&st);//访问右子树cur = top->_right;}printf("\n");
}
2、中序遍历
当前节点先压栈不能访问,只有左子树访问完之后,才能访问最后压栈的节点以及他的右子树
void MidOrder(Node *root)//中序遍历非递归
{printf("前序遍历#: ");stack st;stackInit(&st);Node *cur = root;Node *top;while (cur || stackEmpty(&st) != 1){while (cur){stackInsert(&st, cur);cur = cur->_left;}top = stackTop(&st);stackDel(&st);printf("%c ", top->_data);cur = top->_right;}printf("\n");
}
3、后序遍历
后序遍历相对于前两种有点麻烦,看不懂了可以私聊我
void EndOrder(Node *root)//后序遍历非递归
{printf("前序遍历#: ");stack st;stackInit(&st);Node *cur = root;Node *top;Node *prev = NULL;while (cur || stackEmpty(&st) != 1){while (cur){stackInsert(&st, cur);cur = cur->_left;}top = stackTop(&st);if (top->_right == NULL || top->_right == prev){printf("%c ", top->_data);stackDel(&st);prev = top;}else{cur = top->_right;}}printf("\n");
}
代码如下
#include<stdio.h>
#include<windows.h>
#pragma warning(disable:4996)
//定义一个栈可以实现入栈出栈获取栈顶元素的操作
#define num 10
typedef char BDataType;
typedef struct Node//定义树的一个节点
{struct Node *_left;struct Node *_right;BDataType _data;
}Node;
typedef Node* SDataType;
typedef struct stack//定义栈
{SDataType *_array;int _count;//总容量大小int _size;//当前元素大小
}stack;
void stackInit(stack *st)//栈的初始化
{st->_array = (SDataType*)malloc(sizeof(SDataType)*num);st->_count = num;st->_size = 0;
}
void stackInsert(stack *st, SDataType value)//入栈
{if (st->_size == st->_count)//空间已满,需要扩容{st->_array = (SDataType*)realloc(st->_array, sizeof(SDataType)*(2 * st->_count));st->_count = 2 * st->_count;}st->_array[st->_size] = value;st->_size++;
}
void stackDel(stack *st)//出栈
{if (st->_size == 0){printf("栈以为空,不能出栈!!!\n");}st->_size--;
}SDataType stackTop(stack *st)//获取栈顶元素
{return st->_array[st->_size - 1];
}
int stackEmpty(stack *st)//判断栈是否为空
{if (st->_size == 0){return 1;}return 0;
}
//用栈来实现二叉树的非递归的三种遍历方法
//先创建一个树
Node *TreeCreat(BDataType *array, int *pos)//创建一棵树,后面会对这棵树进行各种排序
{if (array[*pos] != '#'){Node *root = (Node *)malloc(sizeof(Node));root->_data = array[*pos];(*pos)++;root->_left = TreeCreat(array, pos);(*pos)++;root->_right = TreeCreat(array, pos);return root;}else{return NULL;}
}
//1、前序遍历
void preOrder(Node *root)//前序遍历非递归
{printf("前序遍历#: ");stack st;stackInit(&st);Node *cur = root;Node *top;while (cur || stackEmpty(&st) != 1){while (cur){printf("%c ", cur->_data);stackInsert(&st, cur);cur = cur->_left;}top = stackTop(&st);stackDel(&st);cur = top->_right;}printf("\n");
}
//2、中序遍历
void MidOrder(Node *root)//中序遍历非递归
{printf("前序遍历#: ");stack st;stackInit(&st);Node *cur = root;Node *top;while (cur || stackEmpty(&st) != 1){while (cur){stackInsert(&st, cur);cur = cur->_left;}top = stackTop(&st);stackDel(&st);printf("%c ", top->_data);cur = top->_right;}printf("\n");
}
//3、后序遍历
void EndOrder(Node *root)//后序遍历非递归
{printf("前序遍历#: ");stack st;stackInit(&st);Node *cur = root;Node *top;Node *prev = NULL;while (cur || stackEmpty(&st) != 1){while (cur){stackInsert(&st, cur);cur = cur->_left;}top = stackTop(&st);if (top->_right == NULL || top->_right == prev){printf("%c ", top->_data);stackDel(&st);prev = top;}else{cur = top->_right;}}printf("\n");
}
int main()
{BDataType array[100];//定义一个char数组scanf("%s", array);int pos = 0;Node *root = TreeCreat(array, &pos);preOrder(root);//前序遍历MidOrder(root);//中序遍历EndOrder(root);//后序遍历system("pause");return 0;
}