二叉树的基本操作(总结)
2017-11-21 23:05
351 查看
二叉树的基本操作
二叉树的定义决定了其大多数操作都可以由递归去实现本文通过递归和非递归两种方式实现二叉树的基本操作(加深对原理的理解)
1.二叉树的声明
typedef char ElementType; typedef struct TreeNode* BinTree; struct TreeNode{ ElementType Data; struct TreeNode* Left; struct TreeNode* Right; };
2.遍历
(1)递归实现
>1 先序遍历
按照“根节点-左儿子-右儿子”的顺序访问void PreorderTraversal(BinTree BT) { if (!BT) return; //空树,直接返回 visit(BT->Data); PreorderTraversal(BT->Left); //递归遍历左子树 PreorderTraversal(BT->Right); //递归遍历右子树 }
>2 中序遍历
按照“左儿子-根节点-右儿子”的顺序访问void InorderTraversal(BinTree BT){ if(!BT) return ; InorderTraversal(BT->Left); visit(BT->Data); InorderTraversal(BT->Right); }
>3 后序遍历
按照“左儿子-右儿子-根节点”的顺序访问void PostorderTraversal(BinTree BT){ if(!BT) return ; InorderTraversal(BT->Left); InorderTraversal(BT->Right); visit(BT->Data); }
(2)非递归实现(二叉树的非递归实现借助栈来实现)
属于哪种遍历取决于根节点第几次遇到时访问>1 先序遍历(首次遇到时访问)
//C语言实现 int MaxSize = 1000; void PreorderTraversalRecur(BinTree BT) { TreeNode* St[MaxSize], *p; //创建一个栈 int top = -1; //top的下一个位置指向栈顶 if (!BT) { St[++top] = BT; //根节点入栈 while (top > -1) { p = St[top]; top--; printf("%c ", p->Data); //先序遍历,第一次遇到(入栈)时就访问 //左右子树压栈 if (!p->Left) St[++top] = p->Left; if (!p->Right) St[++top] = p->Right; } } }
//C++实现 void PreOrderTraversal(BinTree BT) { if (!BT) return; stack<BinTree> s; BinTree temp; s.push(BT); while (!s.empty()) { temp = s.top(); printf("%c ", temp->Data); s.pop(); if (temp->Left) s.push(temp->Left); if (temp->Right) s.push(temp->Right); } }
>2 中序遍历
void InorderTraversal(BinTree BT) { TreeNode *St[MaxSize], *node; int top = -1; if (!BT) { node = BT; while (top > -1 || node != NULL) { //先把所有的左子树压栈 while (node != NULL) { St[++top] = node; node = node->Left; } //回溯,访问最后入栈的结点的右子树 if (top > -1) { node = St[top--]; //取除栈顶元素,并且top-- printf("%c ", node->Data); //此时第二次遇到根节点,访问 node = node->Right; } } } }
void InOrderTravel(BinTree BT) { if (!BT) return; stack<BinTree> s; BinTree node = BT; while (!node || !s.empty()) { while (!s.empty() || node) { //一直遍历到左子树最下边,边遍历边保存根节点到栈中 while (node) { s.push(node); node = node->Left; } //当p为空时,说明已经到达左子树最下边,这时需要出栈了 if (!s.empty()) { node = s.top(); s.pop(); printf("%c ", node->Data); //进入右子树,开始新的一轮左子树遍历(这是递归的自我实现) node = node->Right; } } /* //另解 while (!s.empty() || node) { if (node) { s.push(node); node = node->Left; } else { node = s.top(); s.pop(); printf("%c ", node->Data); node = node->Right; } } */ } }
>3 后序遍历
//C++实现 void PostorderTraversalRecursion(BinTree BT) { if (!BT) return; stack<BinTree> s; //pCur:当前访问节点,pLast:上次访问节点 BinTree pCur, pLast; pCur = BT; pLast = NULL; //把左子树结点全部压栈 while (pCur) { s.push(pCur); pCur = pCur->Left; } //已经遍历到左子树底端 while (!s.empty()) { pCur = s.top(); s.pop(); if (pCur->Left == pLast) { //若左子树刚被访问过,则需先进入右子树(根节点需再次入栈) //根节点再次入栈 s.push(pCur); //进入右子树,且可肯定右子树一定不为空 pCur = pCur->Right; while (pCur) { s.push(pCur); pCur = pCur->Right; } } //一个根节点被访问的前提是:无右子树或右子树已被访问过 else if (pCur->Right == NULL || pCur->Right == pLast) { printf("%c ", pCur->Data); //修改最近被访问的节点 pLast = pCur; } } }
参考:http://blog.csdn.net/zhangxiangdavaid/article/details/37115355
层序遍历(利用队列实现)
>1 C语言实现队列
void LevelorderTraversal(BinTree BT) { BinTree q[1000]; BinTree temp; int head = 0, tail = 0; if (!BT) return; else { q[tail++] = BT; while (tail != head) { temp = q[head++]; printf(" %c", temp->Data); if (temp->Left) q[tail++] = temp->Left; if (temp->Right) q[tail++] = temp->Right; } } }
2> C++(queue)实现
void LevelorderTraversal(BinTree BT) { queue <BinTree> q; BinTree temp; if (!BT) return; else { q.push(BT); //根节点入队 while (!q.empty()) { temp = q.front(); q.pop(); //队首元素出队,并访问 cout << temp->Data << ' '; if (temp->Left) q.push(temp->Left); //左儿子入队 if (temp->Right) q.push(temp->Right); //右儿子入队 } } }
3.其他操作
(1)求树的高度
int GetHeight(BinTree BT) { /* if (BT == NULL) return 0; else return 1 +(GetHeight(BT->Left) > GetHeight(BT->Right) ? GetHeight(BT->Left): GetHeight(BT->Right)); */ int h = 0; if (BT == NULL) { return 0; } int lh = GetHeight(BT->Left) + 1; int rh = GetHeight(BT->Right) + 1; h = lh > rh ? lh : rh; return h; }
(2)求二叉树结点的个数
int Nodenum(BinTree BT) { if(!BT) return 0; else return 1+Nodenum(BT->Left)+Nodenum(BT->Right); }
(3)求叶子结点的个数
int LeavesCount(BiTree BT) { if(!BT == NULL) return 0; //BT为空树,返回0 int cnt = 0; if(!(BT->LChild || BT->RChild)) ++cnt; //BT为叶子结点,加1 else { //递归求左子树上的叶子结点,并累加 cnt += LeavesCount(BT->LChild); //递归求右子树上的叶子结点,并累加 cnt += LeavesCount(BT->RChild); } return cnt; }
本人才疏学浅,如有错误,欢迎大家指正
相关文章推荐
- 二叉树学习总结:二叉树的基本操作、遍历二叉树、中序线索化二叉树、中序遍历线索二叉树
- 二叉树的基本操作及编程题总结(C++)
- 基本数据结构学习总结: 二叉树的基本操作
- 树的术语、二叉树的性质、二叉树的基本操作总结
- Linux笔记--vim的基本常用操作总结
- 树 二叉树的建立和基本操作
- 二叉树的链式存储和基本操作
- c++学习笔记—二叉树基本操作的实现
- 二叉树的基本操作
- 数据结构->二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作小结
- 二叉树基本操作
- 二叉树的基本操作
- 二叉树的基本操作方式
- 二叉树基本操作的程序实现
- c++ 基本操作 考点总结(三)
- 二叉树基本操作汇总练习
- 二叉树基本操作
- 二叉树的基本操作实现(递归和非递归)