【C语言】用链表实现的堆栈来实现二叉树的前中后序遍历
2020-04-01 19:15
971 查看
/* 二叉树的前中后序遍历 */ #include <stdio.h> #include <stdlib.h> typedef struct treeNode *BinTree; typedef struct stackNode *Stack; /* 二叉树的描述结构 */ struct treeNode { int data; struct treeNode *left; struct treeNode *right; }; /* 栈的结构 */ struct stackNode { BinTree node; struct stackNode *next; }; /* 链表实现堆栈 */ Stack createStack(){ Stack stack = (Stack)malloc(sizeof(struct stackNode)); stack->next = NULL; return stack; } /* 判断栈是否为空 */ int stackIsEmpty(Stack stackTop){ if (stackTop->next) return 0; return 1; } /* 压栈 */ void stackPush(Stack stackTop, BinTree myNode){ if (myNode) { Stack midNode = (Stack)malloc(sizeof(struct stackNode)); midNode->node = myNode; midNode->next = stackTop->next; stackTop->next = midNode; } } /* 出栈 */ BinTree stackPop(Stack stackTop){ if (stackIsEmpty(stackTop)) { printf("Stack is empty!\n"); return NULL; } BinTree mid = stackTop->next->node; Stack willFree = stackTop->next; stackTop->next = willFree->next; free(willFree); return mid; } /* 建立树节点 */ BinTree buildTreeNode(int myData){ BinTree mid = (BinTree)malloc(sizeof(struct treeNode)); mid->left = NULL; mid->right = NULL; mid->data = myData; return mid; } /* 后序时前驱节点 */ BinTree frontNode(BinTree node){ if (node->right) return node->right; return node->left; } /* 递归实现先序遍历 */ void ergodicBinTree1(BinTree myTree){ if (myTree) { printf("%d ", myTree->data); ergodicBinTree1(myTree->left); ergodicBinTree1(myTree->right); } } /* 递归实现中序遍历 */ void ergodicBinTree2(BinTree myTree){ if (myTree) { ergodicBinTree2(myTree->left); printf("%d ", myTree->data); ergodicBinTree2(myTree->right); } } /* 递归实现后序遍历 */ void ergodicBinTree3(BinTree myTree){ if (myTree) { ergodicBinTree3(myTree->left); ergodicBinTree3(myTree->right); printf("%d ", myTree->data); } } /* 堆栈实现先序遍历 */ /* 大概思路: 1.从树根往左遍历到头,将节点的右子节点压栈; 2.到头以后说明该节点已经没有左子节点了,可以开始将右子节点当做子树头来进行出栈; */ void ergodicBinTree4(BinTree myTree){ Stack stackTop = createStack(); while(myTree){ /* 从根开始,往左遍历到头 */ while(myTree){ printf("%d ", myTree->data); //遇到就进行输出 stackPush(stackTop, myTree->right); //并将该节点的右节点进行压栈(压栈操作会自己判断数据是否有效) myTree = myTree->left; //将该节点的左节点当做根节点去再进行以上操作 } /* 将最近的右孩子当做子树的根,因为此时栈里存的都是右节点,所以得考虑到只有左线性的情况,需要判断一下(其实出栈操作会判断是否为空,所以也可以不进行判断) */ if (!stackIsEmpty(stackTop)) myTree = stackPop(stackTop); } } /* 堆栈实现中序遍历 思路: 1.因为先进行左子树的输出,所以当遇到节点的时候,暂时还不知道能不能输出,所以需要先将它存下来; 2.当到达左子树的最后一个的时候,就可以将节点进行出栈输出,并将该节点的右节点当做子树的根进行以上操作; PS:由于当左边遍历到最后一个的时候,如果该节点为叶子节点,那么指向的时候也会为空,所以循环的结束条件是节点与堆栈都为空。 */ void ergodicBinTree5(BinTree myTree){ Stack stackTop = createStack(); while(myTree || !stackIsEmpty(stackTop)){ while(myTree){ stackPush(stackTop, myTree); myTree = myTree->left; } if (!stackIsEmpty(stackTop)) { myTree = stackPop(stackTop); printf("%d ", myTree->data); myTree = myTree->right; } } } /* 堆栈实现后序遍历 PS:前驱节点:当前驱节点已经被弹出,那它自己也可以弹出了,叶子节点没有前驱节点; 思路: 1.与中序时一样,先遍历到左边最后一个,并进行节点压栈; 2.左边最后一个可能有右子节点,所以需要判断一下,如果没有前驱节点,就进行输出,并重置上一次输出的节点(用于判断栈中节点是否可以出栈),否则将节点当做子树根再进行遍历; */ void ergodicBinTree6(BinTree myTree){ Stack stackTop = createStack(); BinTree last = NULL; while(myTree || !stackIsEmpty(stackTop)){ while(myTree){ stackPush(stackTop, myTree); myTree = myTree->left; } if (!stackIsEmpty(stackTop)) { BinTree judge = stackTop->next->node->right; if (judge) { myTree = judge; //判断是否有右子节点,有就把它当做子树的根节点先行遍历 }else{ last = stackPop(stackTop); //如果没有右子节点,那说明为叶子节点,将其弹出 printf("%d ", last->data); while(!stackIsEmpty(stackTop) && last == frontNode(stackTop->next->node)){ //当弹出一个叶子节点之后,需要将前驱节点已经弹出的全部都弹出 last = stackPop(stackTop); printf("%d ", last->data); } myTree = NULL; //弹出前面的节点以后,说明该子树已经遍历完,不再进行重复遍历,PS:其实进到这里的时候myTree就表明是空的,也可以不进行赋值。 } } } } int main(int argc, char const *argv[]) { BinTree temp; BinTree myTree = buildTreeNode(1); myTree->right = buildTreeNode(2); temp = myTree->right; temp->left = buildTreeNode(3); temp->right = buildTreeNode(4); temp = temp->right; temp->left = buildTreeNode(5); temp->right = buildTreeNode(6); temp->left->right = buildTreeNode(7); temp->left->right->left = buildTreeNode(9); temp = temp->right; temp->left = buildTreeNode(8); temp = temp->left; temp->right = buildTreeNode(10); temp = temp->right; temp->right = buildTreeNode(11); ergodicBinTree1(myTree); printf("\n"); ergodicBinTree2(myTree); printf("\n"); ergodicBinTree3(myTree); printf("\n"); printf("\n"); ergodicBinTree4(myTree); printf("\n"); ergodicBinTree5(myTree); printf("\n"); ergodicBinTree6(myTree); printf("\n"); return 0; }
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- 迭代实现二叉树的前中后序遍历
- C语言递归实现二叉树的先序、中序、后序遍历
- C语言非递归实现二叉树的先序、中序、后序、层序遍历
- c语言实现二叉树先序,中序,后序(递归),层次遍历,求叶子节点个数及树的深度,下一篇写非递归的遍历
- 二叉树 前中后序遍历非递归版本 C++实现
- 树和二叉树---C语言利用栈实现二叉树的递归、非递归的前、中、后序遍历
- 二叉树的中序、先序、后序遍历非递归遍历算法(使用堆栈,用循环实现)
- C语言数据结构(14)--二叉树的前序、中序、后序、层序遍历算法及代码实现
- 【C语言】链表实现队列,队列实现二叉树的广度优先(层次)遍历
- 二叉树前序、中序、后序非递归遍历实现(C语言)
- 递归、非递归实现二叉树的前中后序遍历
- C语言实现二叉树(创建,先序,中序,后序遍历的递归实现,以及非递归的中序遍历(栈),求树的高度)
- C语言实现 前序、中序、后序遍历二叉树
- 用c语言创建一颗二叉树,用递归方法实现对其进行先序、中序和后序遍历的操作。
- 【数据结构】二叉树的前中后序遍历递归和非递归实现
- 数据结构-----后序遍历二叉树非递归算法(利用堆栈实现)
- c语言实现二叉树的先序遍历,中序遍历,后序遍历
- c语言实现二叉树的建立与前序、中序、后序、层序遍历
- 数据结构 二叉树的先序 中序 后序遍历(linux 下c语言实现)
- 二叉树的建立以及先序、中序、后序遍历C语言实现