递归是程序设计中强有力的工具。递归函数结构清晰,使程序易读。但递归函数也有不可克服的弱点,时间、空间效率较低,运行代价较高,所以在实际使用中,常希望使用它的迭代版本。为了实现非递归遍历算法,需要一个堆栈,作为实现算法的辅助数据结构。堆栈用于存放遍历过程中待处理的任务线索。二叉树是非线性数据结构,遍历过程中访问的每一个结点都有左、右两棵子树,任何时刻程序只能访问其中之一,程序必须保留以后继续访问另一棵子树的“线索”,我们用堆栈来存放这种线索。二叉树遍历的递归算法虽然没有用户定义的栈,但是系统栈承担了此项任务。
#include
#include
#define STACKSIZE 100
typedef char BTNDataType;
typedef struct BinaryTreeNode
{
BTNDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
typedef struct binarytree
{
BTNode* root;
}BT;
void TreeCreate(BT* B1)
{
B1->root = NULL;
}
BTNode* NewNode(BTNDataType x, BTNode* ln, BTNode* rn)
{
BTNode* p = (BTNode*)malloc(sizeof(BTNode));
p->data = x;
p->left = ln;
p->right = rn;
return p;
}
BTNDataType TreeRoot(BT* B1)
{
if (B1->root)
{
return B1->root->data;//树的根节点的数据域
}
else
{
printf("树为空\n");
exit(-1);
}
}
void TreeMake(BT* B1, BTNDataType x, BT* lt, BT* rt)//传入树B1,数据x,左子树lt,右子树rt
{
if (B1->root || lt == rt)//如果rt==lt,则左右子树共享结点
{
return;
}
B1->root = NewNode(x, lt->root, rt->root);
lt->root = rt->root = NULL;
}
void PrevOrder(BTNode* root)//先序遍历
{
if (root == NULL)
{
return;
}
printf("%c ", root->data);//根结点
PrevOrder(root->left);//左子树
PrevOrder(root->right);//右子树
}
void MidOrder(BTNode* t) //t为根指针
{
struct BTNode* st[STACKSIZE];//定义指针栈
int top = 0; //置空栈
do {
while (t) //根指针t表示的为非空二叉树
{
if (top == STACKSIZE)
{
exit(-1);//栈已满,退出
}
st[top] = t; //根指针进栈
top++;
t = t->left;//t移向左子树
} //循环结束表示以栈顶元素的指向为根结点的二叉树
//的左子树遍历结束
if (top) //为非空栈
{
top--;
t = st[top]; //弹出根指针
printf("%c", t->data); //访问根结点
t = t->right; //遍历右子树
}
} while (top || t); //父结点未访问,或右子树未遍历
}
void InOrder(BTNode* t)//中序遍历
{
if (t == NULL)
{
return;
}
InOrder(t->left);
printf("%c", t->data);
InOrder(t->right);
}
void NodeDestory(BTNode* root)
{
if (!root)
{
return;
}
NodeDestory(root->left);
NodeDestory(root->right);
free(root);
}
void TreeDestory(BT* B1)
{
NodeDestory(B1->root);
}
主函数,创造一个二叉树并且将递归与非递归算法的中序遍历对比:
int main()
{
BT a, b, x, y, z;
TreeCreate(&a);
TreeCreate(&b);
TreeCreate(&x);
TreeCreate(&y);
TreeCreate(&z);
TreeMake(&y, 'E', &a, &b);
TreeMake(&z, 'F', &a, &b);
TreeMake(&x, 'C', &y, &z);
TreeMake(&y, 'D', &a, &b);
TreeMake(&z, 'B', &y, &x);
//PrevOrder((&z)->root);
printf("中序非递归遍历\n");
MidOrder((&z)->root);
printf("中序递归遍历\n");
InOrder((&z)->root);
TreeDestory(&z);
system("pause");
return 0;
}