最近在看树的数据结构,看到树的遍历,于是写了一下树的中序遍历的递归和非递归程序。这里会用到两种数据结构,一种是栈(非递归),一种是二叉树的数据结构。
二叉树的数据结构定义如下:
typedef struct TNode//二叉树结构
{
char nodeValue;//结点的值
TNode* left;//左子树
TNode* right;//右子树
}*BiTree;
栈的数据结构:
typedef struct Sqstack
{
BiTree *base; //双重指针,base指向一二叉树结点的指针
BiTree *top;
int stacksize;
}Sqstack;
这里栈的空间用于存储结点的指针。stacksize是栈的总空间。
一些涉及栈的元素的操作:
建立空栈:
void Initstack(Sqstack &S){
S.base=(BiTree*)malloc(maxstack_size*sizeof(BiTree));
S.top=S.base;
S.stacksize=maxstack_size;
}
判断是否为空栈:
bool stackempt(Sqstack S){
if(S.base==S.top) return true;
else return false;
}
元素入栈:
//将一个元素插入栈顶
void push(Sqstack &S,BiTree e){
//如果栈满则重新分配一个increase_size大小的空间给栈
if(S.top-S.base>=S.stacksize){
S.base=(BiTree*)realloc(S.base,(S.stacksize+increase_size)*sizeof(BiTree));
S.top=S.base+S.stacksize;
S.stacksize+=increase_size;
}
*S.top=e;
S.top++;
}
元素出栈:
//将栈顶元素退出并赋值给e
void pop(Sqstack &S,BiTree &q){
if(stackempt(S)) return;
S.top--;
q=*S.top;
}
接下来就是建立一个二叉树了,先序建立一棵二叉树最简单,程序如下:
void CreateBiTree(BiTree &T)//先序遍历方式创建二叉树 ,输入.代表该结点为空
{
char nodeValue;
cin>> nodeValue;
if(nodeValue!='.')//结点非空
{
T=new TNode;
T->nodeValue=nodeValue;
CreateBiTree(T->left);
CreateBiTree(T->right);
}
else T=NULL;
}
然后是中序遍历的递归程序:
//树中根遍历的递归
void inordervisit(BiTree T){
if(T){
inordervisit(T->left);
printf("%c",T->nodeValue);
inordervisit(T->right);
}else{
// printf(".");
}
}
中序遍历的非递归程序:
//树中根遍历的非递归
void inorder(BiTree T,Sqstack S){
if(T){
BiTree q=T;
while(q||!stackempt(S)){
while(q){
push(S,q);q=q->left;
}
// printf(".");
pop(S,q);
printf("%c",q->nodeValue);
if(q->right){
q=q->right;
}else{
// printf(".");
if(!stackempt(S)){
pop(S,q);
printf("%c",q->nodeValue);
} //栈若为空则会重复输出最后一个元素值
q=q->right;
}
}
}
}
以下是完整代码段:
#include<stdio.h>
#include<iostream>
#include<malloc.h>
using namespace std;
#define maxstack_size 100
#define increase_size 10
/*树的中根遍历递归和非递归*/
typedef struct TNode//二叉树结构
{
char nodeValue;//结点的值
TNode* left;//左子树
TNode* right;//右子树
}*BiTree;
typedef struct Sqstack
{
BiTree *base; //双重指针,base指向一二叉树结点的指针
BiTree *top;
int stacksize;
}Sqstack;
void CreateBiTree(BiTree &T)//先序遍历方式创建二叉树 ,输入.代表该结点为空
{
char nodeValue;
cin>> nodeValue;
if(nodeValue!='.')//结点非空
{
T=new TNode;
T->nodeValue=nodeValue;
CreateBiTree(T->left);
CreateBiTree(T->right);
}
else T=NULL;
}
//树中根遍历的递归
void inordervisit(BiTree T){
if(T){
inordervisit(T->left);
printf("%c",T->nodeValue);
inordervisit(T->right);
}else{
// printf(".");
}
}
//空栈建立
void Initstack(Sqstack &S){
S.base=(BiTree*)malloc(maxstack_size*sizeof(BiTree));
S.top=S.base;
S.stacksize=maxstack_size;
}
//判断一个栈是否为空栈,如果是空栈返回true,否则返回false
bool stackempt(Sqstack S){
if(S.base==S.top) return true;
else return false;
}
//将一个元素插入栈顶
void push(Sqstack &S,BiTree e){
//如果栈满则重新分配一个increase_size大小的空间给栈
if(S.top-S.base>=S.stacksize){
S.base=(BiTree*)realloc(S.base,(S.stacksize+increase_size)*sizeof(BiTree));
S.top=S.base+S.stacksize;
S.stacksize+=increase_size;
}
*S.top=e;
S.top++;
}
//将栈顶元素退出并赋值给e
void pop(Sqstack &S,BiTree &q){
if(stackempt(S)) return;
S.top--;
q=*S.top;
}
//树中根遍历的非递归
void inorder(BiTree T,Sqstack S){
if(T){
BiTree q=T;
while(q||!stackempt(S)){
while(q){
push(S,q);q=q->left;
}
// printf(".");
pop(S,q);
printf("%c",q->nodeValue);
if(q->right){
q=q->right;
}else{
// printf(".");
if(!stackempt(S)){
pop(S,q);
printf("%c",q->nodeValue);
} //栈若为空则会重复输出最后一个元素值
q=q->right;
}
}
}
}
int main(){
BiTree T;
Sqstack S;
printf("请按先序序列输入二叉树的结点,“.”代表空结点:\n");
CreateBiTree(T); //建树
Initstack(S); //建栈
printf("中根遍历的递归输出如下:\n");
inordervisit(T);
printf("\n中根遍历的非递归输出如下:\n");
inorder(T,S);
return 0;
}
内容总结:
在写程序的过程中,应该把被调用程序写在调用程序之前,因为程序是顺序执行。栈空间存储不只是内容,还可以是指针一类的东西。realloc重分配函数的使用