一. 实验要求
实现二叉树创建算法,在此基础上实现二叉树的先序、后序递归遍历算法、两种非递归中序遍历、层序遍历、求二叉树的深度。注意:在非递归算法中用到栈和队列时,不要调用系统的栈和队列,需要自己实现栈和队列的操作。
二. 实验目的
通过该实验,理解二叉树的链式存储,掌握二叉树的几种遍历算法,并理解递归的含义,掌握C语言编写递归函数的方法和注意事项。
三. 设计思想
1.首先进行先序创建二叉树。从键盘输入字符c,如果c是‘$’则说明该结点是空;否则,为该结点申请一个空间,让数据data等于c,接着利用递归函数创造这个数据c的左孩子和右兄弟。直到没有左右子树可继续递归为止。
2.先序遍历二叉树。如果结点为空,则不输出;否则,输出结点T的数据data。利用递归思想,继续先序遍历结点T的左子树和右子树,直到遍历完为止。
3.后序遍历二叉树。如果结点为空,则不输出;否则,先递归遍历结点T的左子树和右子树,再输出结点T的data值。
4.中序遍历二叉树1。先申请一个栈S,一个栈顶元素指针top,将根结点T先入栈。当栈S不空时,进行while循环:如果栈不为空且结点不为空时,将栈顶元素data值结点的左孩子入栈;否则,让top指向的栈顶元素出栈,输出栈顶元素的data值,并将栈顶元素的右子树入栈。直到栈为空时,结束遍历。
5.中序遍历二叉树2。先申请一个栈S,一个指针p指向遍历的结点T,一个指针top指向栈顶元素的后一个位置。当指针p不指向空并且栈S存在时,进行while循环:如果指针p存在,将指针p所指向的结点值data入栈,让p指向原位置的左孩子;否则,将栈S中的栈顶元素出栈,输出栈顶元素的data值,并让p指向栈顶元素的右孩子。直到栈为空,结束遍历。
6.层序遍历二叉树。申请一个队列Q,一个指针top指像队头元素。将根结点T入队,当队列Q不为空时,进行while循环:当根结点出队后,令其左、右孩子结点入队(空不入队),而左孩子出队时又令它的左右孩子结点入队,……由此便可产生按层次输出的效果。
7.求二叉树的深度。如果T为空树,返回0;否则,利用High函数递归计算根结点T的左子树和右子树的深度,取最大值。
四. 主要源代码
#include "iostream"
using namespace std;
#define INITIAL 10000
typedef struct Node
{
char data;
Node *left_child, *right_child;
}*Bitree,Node;
struct Stack
{
Bitree *base,*top;
int length;
};
struct Node_q{
Node* data;
Node_q* next;
};
struct Queue{
Node_q *front,*rear;
};
void print();
int max(int a,int b)
{
if(a>b)
{
return a;
}
else
{
return b;
}
}
void Create(Bitree &T)
{
char c;
cin>>c;
if (c == '$') //这个是什么意思??看不懂
{
T = NULL;
}
else
{
T = (Bitree)malloc(sizeof(Node));
T->data = c;
Create(T->left_child);
Create(T->right_child);
}
}
void dlr(Bitree &T)
{
if(!T)
{
return;
}
cout<<T->data<<" ";
dlr(T->left_child);
dlr(T->right_child);
}
void lrd(Bitree &T)
{
if(!T)
{
return;
}
lrd(T->left_child);
lrd(T->right_child);
cout<<T->data<<" ";
}
void Init(Stack &S)
{
S.base=(Bitree*)malloc(INITIAL*sizeof(Bitree));
S.top=S.base;
S.length=INITIAL;
}
void Push(Stack &S,Node* e)
{
if (S.top-S.base>=S.length)
{
S.top=(Bitree*)realloc(S.base,(S.length+10)*sizeof(Bitree));
S.top=S.base+S.length;
S.length+=10;
}
*S.top=e;
S.top++;
}
int Empty(Stack &S)
{
if(S.top==S.base)
{
return true;
}
else
{
return false;
}
}
int Pop(Stack &S, Node* &e)
{
if(Empty(S))
{
return -1;
}
S.top--;
e=*S.top;
return true;
}
int Top(Stack S, Node* &e)
{
if (Empty(S))
{
return -1;
}
e=*(S.top-1);
return true;
}
void ldr_1(Bitree T)
{
Stack S;
Node* top;
Init(S);
Push(S, T);
while(!Empty(S))
{
if((Top(S, top) != -1) && top)
{
Push(S,top->left_child);
}
else
{
Pop(S, top);
if(!Empty(S))
{
Pop(S, top);
cout<<top->data<<endl;
Push(S,top->right_child);
}
}
}
puts("");
}
void ldr_2(Bitree T)
{
Stack S;
Init(S);
Node *p=T,*top;
while (p || !Empty(S))
{
if (p)
{
Push(S, p);
p=p->left_child;
}
else
{
Pop(S, top);
cout<<top->data<<endl;
p = top->right_child;
}
}
puts("");
}
void Init(Queue &Q)
{
Q.front = Q.rear = (Node_q*)malloc(sizeof(Node_q));
Q.front->next = Q.rear->next = NULL;
}
int Empty(Queue Q)
{
if (Q.front == Q.rear)
{
return true;
}
else
{
return false;
}
}
int Top(Queue Q, Node* &e)
{
if (Empty(Q))
{
return -1;
}
e = Q.front->next->data;
return true;
}
int Push(Queue &Q, Node* e)
{
Node_q *p = (Node_q*)malloc(sizeof(Node_q));
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
return true;
}
int Pop(Queue &Q, Node* &e)
{
if (Empty(Q))
{
return -1;
}
Node_q *p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if (p == Q.rear)
{
Q.rear = Q.front;
}
free(p);
return true;
}
void Level(Bitree T)
{
Queue Q;
Init(Q);
Push(Q, T);
Node *top;
while(!Empty(Q))
{
Pop(Q, top);
if (!top)
{
continue;
}
cout<<top->data<<endl;
Push(Q, top->left_child);
Push(Q, top->right_child);
}
puts("");
}
int High(Bitree T)
{
if(!T)
{
return 0;
}
return max(High(T->left_child), High(T->right_child)) + 1;
}
int main()
{
print();
int t;
cin>>t;
Bitree T;
while (cin >> t)
{
if (t == 8)
{
break;
}
switch(t)
{
case 1: // 创建
{
getchar();
Create(T);
break;
}
case 2: // 先序
{
printf("先序: ");
dlr(T);
puts("");
break;
}
case 3: // 中序1
{
printf("中序1: ");
ldr_1(T);
break;
}
case 4: // 中序2
{
printf("中序2: ");
ldr_2(T);
break;
}
case 5: // 后序
{
printf("后序: ");
lrd(T);
puts("");
break;
}
case 6: // 层序
{
printf("层序: ");
Level(T);
break;
}
case 7: // 深度
{
printf("深度: %d\n", High(T));
break;
}
default:
{
printf("输入序号错误! ");
break;
}
}
cout << "请输入你的选择:";
}
return 0;
}
void print()
{
cout << "**************************************************************\n";
cout << "****************** 1.创建二叉树 ******************\n";
cout << "****************** 2.先序遍历二叉树 ******************\n";
cout << "****************** 3.中序遍历二叉树1 ******************\n";
cout << "****************** 4.中序遍历二叉树2 ******************\n";
cout << "****************** 5.后序遍历二叉树 ******************\n";
cout << "****************** 6.层序遍历二叉树 ******************\n";
cout << "****************** 7.求二叉树的深度 ******************\n";
cout << "****************** 8.退出 ******************\n";
cout << "**************************************************************\n";
cout << "请输入你的选择:";
}
五. 调试与测试数据