利用栈的非递归先序遍历二叉树:
额,这个是我自己写的,可能算法有点啰嗦……
/********** 【题目】试利用栈及其基本操作写出二叉树T的非递归 的先序遍历算法。 二叉链表类型定义: typedef struct BiTNode { TElemType data; struct BiTNode *lchild,*rchild; } BiTNode, *BiTree; 可用栈类型Stack的相关定义: typedef BiTree SElemType; // 栈的元素类型 Status InitStack(Stack &S); Status StackEmpty(Stack S); Status Push(Stack &S, SElemType e); Status Pop(Stack &S, SElemType &e); Status GetTop(Stack S, SElemType &e); **********/ /*思路:先访问根节点,然后向左一直走下去,每走一个都是先访问根节点,并沿途把右子树入栈。向左走完后,开始搞栈里面的元素, 对栈里面的元素,先看它的右子树存不存在,若存在则入栈,然后再对这个元素的右子树也进行向左走操作*/ void traverseLeft(BiTree T, Stack &S, void (*visit)(TElemType)); Stack S; void PreOrder(BiTree T, void (*visit)(TElemType)) /* 使用栈,非递归先序遍历二叉树T, */ /* 对每个结点的元素域data调用函数visit */ { InitStack(S); BiTree tree2 = T; BiTree treeTemp = tree2; while(treeTemp && treeTemp->data!='#') { //好吧做了后面的题后发现好像可以不用这个data='#',但懒得改了 visit(treeTemp->data); printf("visit the root:%c ",treeTemp->data); traverseLeft(treeTemp->lchild, S, visit);//遍历左边的节点,并沿途将他们的右子树入栈,遍历后treeTemp指向最左边那个子树 while(!StackEmpty(S)) { printf("get into the stack "); Pop(S, treeTemp); visit(treeTemp->data); printf("visit the stack of the rchild:%c ",treeTemp->data); if(treeTemp->rchild && treeTemp->rchild->data!='#') { Push(S, treeTemp->rchild); } traverseLeft(treeTemp->lchild, S, visit); } treeTemp = tree2->rchild; tree2 = tree2->rchild; } } void traverseLeft(BiTree T, Stack &S, void (*visit)(TElemType)) { while(T && T->data!='#') { visit(T->data); printf("visit the lchild:%c ",T->data); if(T->rchild && T->data!='#') { Push(S, T->rchild); if(!StackEmpty(S)) { printf("push %c into the stack ",T->rchild->data); } } T = T->lchild; } }
利用栈实现非递归后序遍历二叉树:
这个是网上找的实现算法:
/********** 【题目】试利用栈及其基本操作写出二叉树T的非递归 的后序遍历算法(提示:为分辨后序遍历时两次进栈的 不同返回点,需在指针进栈时同时将一个标志进栈)。 二叉链表类型定义: typedef struct BiTNode { TElemType data; struct BiTNode *lchild,*rchild; } BiTNode, *BiTree; 可用栈类型Stack的相关定义: typedef struct { struct BiTNode *ptr; // 二叉树结点的指针类型 int tag; // 0..1 } SElemType; // 栈的元素类型 Status InitStack(Stack &S); Status StackEmpty(Stack S); Status Push(Stack &S, SElemType e); Status Pop(Stack &S, SElemType &e); Status GetTop(Stack S, SElemType &e); **********/ void PostOrder(BiTree T, void (*visit)(TElemType)) /* 使用栈,非递归后序遍历二叉树T, */ /* 对每个结点的元素域data调用函数visit */ { SElemType a,b; //a可以说是主要遍历这个树的一个指针这样的,b是主要用来处理从栈出来的东西 Stack s; a.ptr=T; while(a.ptr){ if(a.ptr->lchild&&a.ptr->rchild){ //如果有两个孩子的话 a.tag=1; Push(s,a); //属于1号 a.ptr=a.ptr->lchild; //走左孩子 } else if(a.ptr->lchild&&!a.ptr->rchild){ //如果只有左孩子的话 a.tag=0; //属于0号 Push(s,a); a.ptr=a.ptr->lchild; //走左孩子 } else if(!a.ptr->lchild&&a.ptr->rchild){ //如果只有右孩子的话 a.tag=0; //属于0号 Push(s,a); a.ptr=a.ptr->rchild; //走右孩子 } else if(!a.ptr->lchild&&!a.ptr->rchild) { //如果是叶子结点的话 (*visit)(a.ptr->data); //先访问这个叶子结点 Pop(s,b); //然后就开始访问栈里面的东西了,出栈,用b来装 if(b.tag==1) //如果栈里面迟来的是个有两个孩子的东西,说明刚刚它走的是左孩子,然后现在要走它的右孩子并把它变成tag为0 { b.tag=0; a.ptr=b.ptr->rchild; //走右孩子 Push(s,b); } else if(b.tag==0) //如果从栈出来的这个是只有一个孩子的,说明它的孩子已经访问过了,因为栈里的已经是往回走了嘛,它进去的时候如果只有一个孩子,那 //回去就说明它的孩子都被访问过了 { a=b; //依然用a来走遍历 while(a.tag==0&&!StackEmpty(s)) //如果栈未空且出来的元素都是tag为0的 { (*visit)(a.ptr->data); Pop(s,a); } if(a.tag==0&&StackEmpty(s)){ //如果栈里面已经没有元素了,就指向NULL,也就是遍历结束 (*visit)(a.ptr->data); a.ptr=NULL; } else if(a.tag==1){ b=a; a.ptr=b.ptr->rchild; b.tag=0; Push(s,b); } } } } }
利用栈的非递归终须遍历二叉树在数据结构课本的p135上