二叉树的基本操作(总结)

来源:互联网 发布:最新营销软件 编辑:程序博客网 时间:2024/05/16 09:00

二叉树的基本操作

二叉树的定义决定了其大多数操作都可以由递归去实现

本文通过递归和非递归两种方式实现二叉树的基本操作(加深对原理的理解)

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;  } 


本人才疏学浅,如有错误,欢迎大家指正