下面这个程序是我看weiss的《数据结构与算法分析》的第四章的树里面的一个算法写的程序,具体可以看该书的第一版的71页这个给出我的实现,希望来者给出更加好的设计思路。
程序里面给出了8种遍历方式,欧拉遍历(其实就是中序加了两个括号而已),前序非递归,中序非递归,后序非递归,前序递归,中序递归,后序递归,
另外程序也添加了按层遍历二叉树,程序如下:
- #include<ctype.h>
- #include<malloc.h>
- #include<stdio.h>
- #include<queue>
- usingnamespacestd;
- typedefstructTreenode*ptrtonode;
- typedefptrtonodeTree;
- structTreenode{
- charx;
- Treelefttree;
- Treerighttree;
- }Treenode;
- typedefstructList_Stack{
- structList_Stack*next;
- Treemytree;
- }Node,*LS;
- voidinitstack(LS*a){
- (*a)=(LS)malloc(sizeof(Node));
- (*a)->next=NULL;
- }
- boolstackempty(constLSa){
- returna->next==NULL;
- }
- /*链栈一般不会满,不测试
- boolstackfull(constLSa){
- return!stackempty(a);
- }
- */
- voidpush(LS*lstack,Treea){
- LSres=(LS)malloc(sizeof(Node));
- res->mytree=a;
- res->next=(*lstack)->next;
- (*lstack)->next=res;
- }
- Treepop(LS*lstack){
- if(stackempty(*lstack)){
- printf("Poperror,stackisempty!\n");
- returnNULL;//打印一个笑脸
- }
- LSp=(*lstack)->next;
- Treex=p->mytree;
- LSpnext=p->next;
- //free(p);
- (*lstack)->next=pnext;
- returnx;
- }
- boolisoperator(chara){
- if(a=='-'||a=='+'||a=='*'||a=='/')
- return1;
- else
- return0;
- }
- Treechartotree(chara){
- Treemytree=(Tree)malloc(sizeof(Treenode));
- mytree->x=a;
- mytree->lefttree=mytree->righttree=NULL;
- returnmytree;
- }
- boolexnode(Treex){//外节点,也就是叶子节点
- if((x->righttree==NULL)&&(x->lefttree==NULL)){
- return1;
- }
- else
- return0;
- }
- boolinnode(Treex){//内节点,也就是中间节点
- return!exnode(x);
- }
- //欧拉遍历方式,跟中序遍历类似
- voideulervisit(Treex){
- if(exnode(x)){
- printf("%c",x->x);
- }
- else{
- printf("(");
- eulervisit(x->lefttree);
- printf("%c",x->x);
- eulervisit(x->righttree);
- printf(")");
- }
- }
- //中序递归的遍历方式
- boolmidvisit(Treex){
- if(x){
- if(midvisit(x->lefttree))
- if(printf("%c",x->x))
- if(midvisit(x->righttree))
- return1;
- return0;
- }
- else
- return1;
- }
- //前序递归的遍历方式
- boolprevisit(Treex){
- if(x){
- if(printf("%c",x->x))
- if(previsit(x->lefttree))
- if(previsit(x->righttree))
- return1;
- return0;
- }
- else
- return1;
- }
- //后序递归的遍历方式
- voidpostvisit(Treex){
- if(x){
- postvisit(x->lefttree);
- postvisit(x->righttree);
- printf("%c",x->x);
- }
- }
- //前序的非递归遍历
- voidpreordervisit(Treex){
- LSa;
- initstack(&a);
- Treep=x;
- while(p||!stackempty(a))
- {
- if(p)
- {
- push(&a,p);
- printf("%c",p->x);
- p=p->lefttree;
- }
- else{
- p=pop(&a);
- p=p->righttree;
- }
- }
- }
- //中序的非递归遍历
- voidinordervisit(Treex){
- LSa;
- initstack(&a);
- Treep=x;
- while(p||!stackempty(a))
- {
- if(p)
- {
- push(&a,p);
- p=p->lefttree;
- }
- else{
- p=pop(&a);
- printf("%c",p->x);
- p=p->righttree;
- }
- }
- }
- /***********************************************************************
- /*后序的非递归遍历,后序遍历有点复杂,
- /*要给出一个标记表明左边和右边子树都已经遍历,
- /*这里就不使用开始时候的堆栈了,
- /*用数组堆栈实现效果更加好,惟一的缺点就是堆栈有最大限制*/
- /************************************************************************/
- voidpostordervisit(Treex){
- Treestack[100],p;
- inttag[100],top;
- top=0;
- p=x;
- do
- {
- while(p!=NULL)//扫描左子树,入栈
- {
- top++;
- stack[top]=p;
- tag[top]=0;//右边子树还没有访问设置为0
- p=p->lefttree;
- }
- if(top>0)
- {
- if(tag[top]==1)
- {
- printf("%c",stack[top]->x);
- top--;
- }
- else{
- p=stack[top];
- if(top>0)
- {
- p=p->righttree;
- tag[top]=1;
- }
- }
- }
- }while((p!=NULL)||(top!=0));
- }
- Treecreatetree(char*a){//根据数据结构与算法分析的71页的算法设计一个表达式树
- LSx;
- initstack(&x);
- char*p=a;
- while(*p!='\0'){
- Treea,b;
- Treemytree;
- if(isalpha(*p)){
- mytree=chartotree(*p);
- push(&x,mytree);
- }
- if(isoperator(*p)){
- mytree=chartotree(*p);
- a=pop(&x);
- b=pop(&x);
- mytree->righttree=a;
- mytree->lefttree=b;
- push(&x,mytree);
- }
- p++;
- }
- Treeroot=pop(&x);
- returnroot;
- }
- voiddeletenode(Tree*p){//按层遍历
- queue<Tree>que;
- que.push(*p);
- Treetemp;
- while(!que.empty()){
- temp=que.front();
- que.pop();
- if(temp->lefttree)
- que.push(temp->lefttree);
- if(temp->righttree)
- que.push(temp->righttree);
- //free(temp);
- printf("%c",temp->x);
- temp=NULL;
- }
- }
- intmain(intargc,char*argv[])
- {
- LSx;
- initstack(&x);
- if(stackempty(x))
- printf("stackisempty!\n");
- else
- printf("stackisfull!\n");
- printf("%c\n",pop(&x));
- char*p="abc*+b-";
- Treeroot=createtree(p);
- //等待进一步的实现来实现二叉树的遍历
- //用到exnode和innode函数
- eulervisit(root);
- puts("\n中序递归");
- midvisit(root);
- puts("\n中序非递归");
- inordervisit(root);
- puts("\n前序递归");
- previsit(root);
- puts("\n前序非递归");
- preordervisit(root);
- puts("\n后序递归");
- postvisit(root);
- puts("\n后序非递归");
- postordervisit(root);
- deletenode(&root);
- return0;
- }