• 二叉树的一系列操作


    //二叉树学习过程中的问题和代码集合
    //按先序序列创建二叉树
    //树的高度
    //求树的结点数
    //求二叉树第K层的节点个数
    //求二叉树中叶子节点的个数
    //求二叉树中节点的最大距离
    //两结点最低公共祖先
    //判断二叉树是不是平衡二叉树
    //释放树空间
    //感谢:http://blog.csdn.net/luckyxiaoqiang/article/details/7518888#topic1 #include<iostream> #include<stack> #include<queue> using namespace std; //二叉树结点 typedef int DateType; typedef struct BiTNode{ DateType data; struct BiTNode *lchild,*rchild,*m_pLeft,*m_pRight; }BiTNode,*BiTree; //按先序序列创建二叉树 int CreateBiTree(BiTree &T){ char data; //‘#’表示空树 cin>>data; if(data == '#'){ T = NULL; } else{ T = (BiTree)malloc(sizeof(BiTNode)); T->data = data; CreateBiTree(T->lchild); CreateBiTree(T->rchild); } return 0; } //输出 void Visit(BiTree T){ if(T->data != '#'){ printf("%c ",T->data); } } //先序遍历 void PreOrder(BiTree T){ if(T != NULL){ //访问根节点 Visit(T); //访问左子结点 PreOrder(T->lchild); //访问右子结点 PreOrder(T->rchild); } } //中序遍历 void InOrder(BiTree T){ if(T != NULL){ //访问左子结点 InOrder(T->lchild); //访问根节点 Visit(T); //访问右子结点 InOrder(T->rchild); } } //后序遍历 void PostOrder(BiTree T){ if(T != NULL){ //访问左子结点 PostOrder(T->lchild); //访问右子结点 PostOrder(T->rchild); //访问根节点 Visit(T); } } //树的高度 //Depth(t)= max( Depth(lchild),Depth(rchild) ) + 1 int BinTreeDepth(BiTree t) { int h,h1,h2; if(t == NULL) return 0; else { h1 = BinTreeDepth(t->lchild); h2 = BinTreeDepth(t->rchild); h = max(h1,h2) + 1; return h; } } //求树的结点数 //树的结点数=左子树 + 右子树 + 1; int getNodeNum(BiTree t) { if(t == NULL) return 0; return (getNodeNum(t->lchild)+getNodeNum(t->rchild)+1); } //求二叉树第K层的节点个数 //NodeNum(t,k) = NodeNum(t->lchild,k-1)+NodeNum(t->rchild,k-1) int GetNodeNumKthLevel(BiTree t, int k) { if(t == NULL || k < 1) return 0; if(k == 1) return 1; // 左子树中k-1层的节点个数 int numLeft = GetNodeNumKthLevel(t->lchild, k-1); // 右子树中k-1层的节点个数 int numRight = GetNodeNumKthLevel(t->rchild, k-1); return (numLeft + numRight); } //求二叉树中叶子节点的个数 //左右儿子为NULL //则:LeafNum(t) = LeafNum(t->lchild) + LeafNum(t->rchild); int GetLeafNodeNum(BiTree t) { if(t == NULL) return 0; if(t->lchild ==NULL && t->rchild ==NULL) return 1; int numleft = GetLeafNodeNum(t->lchild); int numright = GetLeafNodeNum(t->rchild); return (numleft + numright); } //求二叉树中节点的最大距离 //MaxDistance(t->lchild)//MacDistance(t->rchild) //MaxLeft(t->lchild)+MaxRight(t->rchild) int GetMaxDistance(BiTree t, int & maxLeft, int & maxRight) { // maxLeft, 左子树中的节点距离根节点的最远距离 // maxRight, 右子树中的节点距离根节点的最远距离 if(t == NULL) { maxLeft = 0; maxRight = 0; return 0; } int maxLL, maxLR, maxRL, maxRR; int maxDistLeft, maxDistRight; if(t->lchild != NULL) { maxDistLeft = GetMaxDistance(t->lchild, maxLL, maxLR); maxLeft = max(maxLL, maxLR) + 1; } else { maxDistLeft = 0; maxLeft = 0; } if(t->rchild != NULL) { maxDistRight = GetMaxDistance(t->rchild, maxRL, maxRR); maxRight = max(maxRL, maxRR) + 1; } else { maxDistRight = 0; maxRight = 0; } return max(max(maxDistLeft, maxDistRight), maxLeft+maxRight); } //两结点最低公共祖先 //如果两个节点分别在根节点的左子树和右子树,则返回根节点 //如果两个节点都在左子树,则递归处理左子树;如果两个节点都在右子树,则递归处理右子树 //求最近公共祖先: /* //应该就是这样的啊,为什么运行的时候出现内存访问冲突的问题........ bool FindNode(BiTree t, DateType x) { if(t == NULL || x == NULL) return false; if(t->data == x) return true; bool found = FindNode(t->lchild, x); if(!found) found = FindNode(t->rchild, x); return found; } DateType GetLastCommonParent(BiTree t ,DateType A,DateType B) { if(FindNode(t->lchild,A)) { if(FindNode(t->rchild,B)) return t->data; else return GetLastCommonParent(t->lchild,A,B); } else { if(FindNode(t->lchild,B)) return t->data; else return GetLastCommonParent(t->rchild,A,B); } } */ //判断二叉树是不是平衡二叉树 //如果左子树和右子树都是AVL树并且左子树和右子树高度相差不大于1,返回真,其他返回假 bool isAVL(BiTree t, int & height) { if(t == NULL) // 空树,返回真 { height = 0; return true; } int heightLeft; bool resultLeft = isAVL(t->lchild, heightLeft); int heightRight; bool resultRight = isAVL(t->rchild, heightRight); // 左子树和右子树都是AVL,并且高度相差不大于1,返回真 if(resultLeft && resultRight && abs(heightLeft - heightRight) <= 1) { height = max(heightLeft, heightRight) + 1; return true; } else { height = max(heightLeft, heightRight) + 1; return false; } } //释放树空间 void DestroyBinTree(BiTree t) { if(t==NULL) return; DestroyBinTree(t->lchild); DestroyBinTree(t->rchild); t->lchild=NULL; t->rchild=NULL; free(t); } //先序遍历(非递归) //思路:访问T->data后,将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,
    //出栈,再先序遍历T的右子树。
    void PreOrder2(BiTree T){ stack<BiTree> stack; //p是遍历指针 BiTree p = T; //栈不空或者p不空时循环 while(p || !stack.empty()){ if(p != NULL){ //存入栈中 stack.push(p); //访问根节点 printf("%c ",p->data); //遍历左子树 p = p->lchild; } else{ //退栈 p = stack.top(); stack.pop(); //访问右子树 p = p->rchild; } }//while } //中序遍历(非递归) //思路:T是要遍历树的根指针,中序遍历要求在遍历完左子树后,访问根,再遍历右子树。
    //先将T入栈,遍历左子树;
    //遍历完左子树返回时,栈顶元素应为T,出栈,访问T->data,再中序遍历T的右子树。 void InOrder2(BiTree T){ stack<BiTree> stack; //p是遍历指针 BiTree p = T; //栈不空或者p不空时循环 while(p || !stack.empty()){ if(p != NULL){ //存入栈中 stack.push(p); //遍历左子树 p = p->lchild; } else{ //退栈,访问根节点 p = stack.top(); printf("%c ",p->data); stack.pop(); //访问右子树 p = p->rchild; } }//while } //后序遍历(非递归) typedef struct BiTNodePost{ BiTree biTree; char tag; }BiTNodePost,*BiTreePost; //后序遍历 void PostOrder2(BiTree T){ stack<BiTreePost> stack; //p是遍历指针 BiTree p = T; BiTreePost BT; //栈不空或者p不空时循环 while(p != NULL || !stack.empty()){ //遍历左子树 while(p != NULL){ BT = (BiTreePost)malloc(sizeof(BiTNodePost)); BT->biTree = p; //访问过左子树 BT->tag = 'L'; stack.push(BT); p = p->lchild; } //左右子树访问完毕访问根节点 while(!stack.empty() && (stack.top())->tag == 'R'){ BT = stack.top(); //退栈 stack.pop(); BT->biTree; printf("%c ",BT->biTree->data); } //遍历右子树 if(!stack.empty()){ BT = stack.top(); //访问过右子树 BT->tag = 'R'; p = BT->biTree; p = p->rchild; } }//while } //层次遍历 void LevelOrder(BiTree T){ BiTree p = T; //队列 queue<BiTree> queue; //根节点入队 queue.push(p); //队列不空循环 while(!queue.empty()){ //对头元素出队 p = queue.front(); //访问p指向的结点 printf("%c ",p->data); //退出队列 queue.pop(); //左子树不空,将左子树入队 if(p->lchild != NULL){ queue.push(p->lchild); } //右子树不空,将右子树入队 if(p->rchild != NULL){ queue.push(p->rchild); } } } int main() { //测试:ABC##DE#G##F### //测试:124##57##8##3#6## BiTree T; cout<<"先序输入二叉树"<<endl; CreateBiTree(T); printf("先序遍历: "); PreOrder(T); printf(" "); printf("先序遍历(非递归): "); PreOrder2(T); printf(" "); printf("中序遍历: "); InOrder(T); printf(" "); printf("中序遍历(非递归): "); InOrder2(T); printf(" "); printf("后序遍历: "); PostOrder(T); printf(" "); printf("后序遍历(非递归): "); PostOrder2(T); printf(" "); printf("层次遍历: "); LevelOrder(T); printf(" "); cout<<endl<<"树的高度为:"<<BinTreeDepth(T)<<endl<<endl; cout<<"结点数"<<getNodeNum(T)<<endl<<endl; cout<<"二叉树第K层的节点个数"<<endl; int k; cin>>k; cout<<"二叉树第K层的节点个数"<<endl;
       cout<<GetNodeNumKthLevel(T,k)<<endl<<endl; cout<<"二叉树中叶子节点的个数"<<endl<<GetLeafNodeNum(T)<<endl<<endl; int maxLeft = 0; int maxRight = 0; cout<<"二叉树中节点的最大距离"<<endl;
      cout<<<<GetMaxDistance(T, maxLeft, maxRight)<<endl<<endl; //cout<<"两结点最低公共祖先"<<endl; //DateType A,B; ///cin>>A>>B; //cout<<GetLastCommonParent(T,A,B)<<endl; int height = 0; cout<<"判断二叉树是不是平衡二叉树"<<endl<<isAVL(T,height)<<endl<<endl; cout <<"释放树空间"<<endl<<endl; DestroyBinTree(T); system("pause"); return 0; }

    总结:

    二叉树的操作主要是用递归,只要用递归的思想就很容易解决问题,可是递归的效率不高,所以在遍历的时候要想想不用递归该怎么做?

    接下来:

    用分层的方法来创建二叉树

    访问内存出错的问题,指针

    线索二叉树、搜索二叉树。

  • 相关阅读:
    HDU 2899 Strange fuction
    HDU 2899 Strange fuction
    HDU 2199 Can you solve this equation?
    HDU 2199 Can you solve this equation?
    Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)
    Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)
    Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)
    Java实现 LeetCode 699 掉落的方块(线段树?)
    Java实现 LeetCode 699 掉落的方块(线段树?)
    Java实现 LeetCode 699 掉落的方块(线段树?)
  • 原文地址:https://www.cnblogs.com/tianjintou/p/4605359.html
Copyright © 2020-2023  润新知