日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

数据结构--二叉树 Binary Tree

發(fā)布時(shí)間:2024/7/5 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构--二叉树 Binary Tree 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 1.概念
    • 2.存儲(chǔ)方式
      • 2.1 鏈?zhǔn)酱鎯?chǔ)(二叉樹(shù)代碼大部分是鏈?zhǔn)綄?shí)現(xiàn)的)
      • 2.2 順序存儲(chǔ)(基于數(shù)組)
    • 3.二叉樹(shù)的遍歷
      • 3.1 基于鏈表的二叉樹(shù)實(shí)現(xiàn)代碼
      • 3.2 基于數(shù)組的二叉樹(shù)實(shí)現(xiàn)代碼
      • 3.3 非遞歸法 二叉樹(shù)遍歷

1.概念

  • 二叉樹(shù),每個(gè)節(jié)點(diǎn)最多有兩個(gè)“叉”,也就是兩個(gè)子節(jié)點(diǎn),分別是左子節(jié)點(diǎn)和右子節(jié)點(diǎn)。不過(guò),二叉樹(shù)并不要求每個(gè)節(jié)點(diǎn)都有兩個(gè)子節(jié)點(diǎn)
  • 滿二又樹(shù),葉子節(jié)點(diǎn)全都在最底層,除了葉子節(jié)點(diǎn)之外,每個(gè)節(jié)點(diǎn)都有左右兩個(gè)子節(jié)點(diǎn)。
  • 完全二叉樹(shù),葉子節(jié)點(diǎn)都在最底下兩層,最后一層的葉子節(jié)點(diǎn)都靠排列,并且除了最后一層,其他層的節(jié)點(diǎn)個(gè)數(shù)都要達(dá)到最大。


2.存儲(chǔ)方式

2.1 鏈?zhǔn)酱鎯?chǔ)(二叉樹(shù)代碼大部分是鏈?zhǔn)綄?shí)現(xiàn)的)

2.2 順序存儲(chǔ)(基于數(shù)組)

  • 根節(jié)點(diǎn)存儲(chǔ)在下標(biāo) i = 1 的位置,那左子節(jié)點(diǎn)存儲(chǔ)在下標(biāo) 2 * i = 2 的位置,右子節(jié)點(diǎn)存儲(chǔ)在 2 * i + 1 = 3 的位置。
  • 以此類推,B節(jié)點(diǎn)的左子節(jié)點(diǎn)存儲(chǔ)在 2 * i = 2 * 2 = 4 的位置,右子節(jié)點(diǎn)存儲(chǔ)在 2 * i + 1 = 2 * 2 + 1 = 5 的位置。

    堆排序中的堆就是完全二叉樹(shù)。

3.二叉樹(shù)的遍歷

void preOrder(Node* root) {if(root==NULL)return;print root; //打印root節(jié)點(diǎn)preOrder(root->1eft);preOrder(root->right); } void inorder(Node* root) {if(root==NULL)return;inorder(root->1eft);print root; //打印root節(jié)點(diǎn)inorder(root->right); } void postorder(Node* root) {if(root==NULL)return;postorder(root->1eft);postorder(root->right);print root; //打印root節(jié)點(diǎn) } void levelorder(Node* root) //按層從左至右打印 {if(root==NULL)return;queue<node*> nodeQueuenodequeue.push(root);while(!nodequeue.empty()) //建立節(jié)點(diǎn)隊(duì)列,打印父節(jié)點(diǎn),入隊(duì)左右子節(jié)點(diǎn),出隊(duì)父節(jié)點(diǎn){node* p = nodeQueue.front();cout << p->data << " ";if(p->left != NULL)nodeQueue.push(p->left);if(p->right != NULL)nodeQueue.push(p->right);nodeQueue.pop();} }

每個(gè)節(jié)點(diǎn)最多會(huì)被訪問(wèn) 2 次, 所以遍歷操作的時(shí)間復(fù)雜度, 跟節(jié)點(diǎn)的個(gè)數(shù) n 成正比,二叉樹(shù)遍歷的時(shí)間復(fù)雜度是 O(n)

3.1 基于鏈表的二叉樹(shù)實(shí)現(xiàn)代碼

/*** @description: 二叉樹(shù),鏈表實(shí)現(xiàn)* @author: michael ming* @date: 2019/5/11 18:03* @modified by: */ #include <iostream> #include <queue> #include <stack> using namespace std; template <class T> struct node {T data;node<T> *left, *right;node<T>():left(NULL), right(NULL){} }; template <class T> class binary_tree { private:int nodelen;node<T> *root; public:binary_tree():nodelen(0), root(NULL){}node<T>* getRoot()const{return root;}node<T>* insert(node<T> * nodep, size_t lv, size_t toplv, int data = 1){if(lv == 0)return NULL;else if(nodep == NULL && lv == toplv){root = new node<T>();nodep = root;}else{nodep = new node<T>();}nodep->data = data;nodelen++;node<T>* l = insert(nodep->left, lv-1, toplv, 2*data);if(l)nodep->left = l; //返回創(chuàng)建好的left節(jié)點(diǎn)l,跟父接上node<T>* r = insert(nodep->right, lv-1, toplv, 2*data+1);if(r)nodep->right = r; //返回創(chuàng)建好的right節(jié)點(diǎn)r,跟父接上return nodep;}void preOrderPrint(node<T> * nodep){if (nodep == NULL)return;cout << nodep->data << " ";preOrderPrint(nodep->left);preOrderPrint(nodep->right);}void inOrderPrint(node<T> * nodep){if (nodep == NULL)return;inOrderPrint(nodep->left);cout << nodep->data << " ";inOrderPrint(nodep->right);}void postOrderPrint(node<T> * nodep){if (nodep == NULL)return;postOrderPrint(nodep->left);postOrderPrint(nodep->right);cout << nodep->data << " ";}void levelOrderPrint(node<T> * nodep) //按層打印{if (nodep == NULL)return;queue<node<T>*> nodequeue;nodequeue.push(nodep);while(!nodequeue.empty()) //建立節(jié)點(diǎn)隊(duì)列,打印父節(jié)點(diǎn),入隊(duì)左右子節(jié)點(diǎn),出隊(duì)父節(jié)點(diǎn){node<T>* p = nodequeue.front();cout << p->data << " ";if(p->left != NULL)nodequeue.push(p->left);if(p->right != NULL)nodequeue.push(p->right);nodequeue.pop();}}void destory_tree(node<T> * nodep){if (nodep == NULL)return;destory_tree(nodep->left);destory_tree(nodep->right);delete nodep;}//-----------------求二叉樹(shù)高度-----------------------int get_height(node<T>* nodep) //遞歸法, 求左右子樹(shù)高度,較大的+1{if(nodep == NULL)return 0;int leftheight = get_height(nodep->left);int rightheight = get_height(nodep->right);return max(leftheight, rightheight) + 1;}int level_get_height(node<T>* nodep) //按層計(jì)算高度{if (nodep == NULL)return 0;queue<node<T>*> nodequeue;node<T>* p = NULL;nodequeue.push(nodep);int height = 0;while(!nodequeue.empty()) //建立節(jié)點(diǎn)隊(duì)列,入隊(duì)左右子節(jié)點(diǎn),出隊(duì)父節(jié)點(diǎn){height++;int n = nodequeue.size();for(int i = 0; i < n; ++i){p = nodequeue.front();if(p->left != NULL)nodequeue.push(p->left);if(p->right != NULL)nodequeue.push(p->right);nodequeue.pop();}}return height;}int stack_get_height(node<T>* nodep) //用棧實(shí)現(xiàn)前序(或后序)遍歷,最大棧長(zhǎng)度即為樹(shù)的高度{if (nodep == NULL)return 0;stack<node<T>*> nodestack;node<T> *temp = NULL;int height = 0;while(nodep != NULL || !nodestack.empty()){if(nodep != NULL){nodestack.push(nodep);nodep = nodep->left;//找到最底端左節(jié)點(diǎn)}else{nodep = nodestack.top();//最底端左節(jié)點(diǎn)的父節(jié)點(diǎn)nodepif(nodep->right != NULL && nodep->right != temp) //右邊有節(jié)點(diǎn),且沒(méi)有進(jìn)過(guò)棧nodep = nodep->right; //進(jìn)入右節(jié)點(diǎn),跳到上個(gè)if查其子樹(shù)else //沒(méi)有子節(jié)點(diǎn),或者子節(jié)點(diǎn)進(jìn)過(guò)棧{if(nodestack.size() > height)height = nodestack.size(); //更新最大高度temp = nodep; //記錄彈棧的節(jié)點(diǎn)到tempnodestack.pop();nodep = NULL;}}}return height;} };int main() {binary_tree<int> btree;btree.insert(btree.getRoot(), 3, 3);btree.preOrderPrint(btree.getRoot());cout << endl << endl;btree.inOrderPrint(btree.getRoot());cout << endl << endl;btree.postOrderPrint(btree.getRoot());cout << endl << endl;btree.levelOrderPrint(btree.getRoot());cout << endl;cout << "height of tree: " << btree.get_height(btree.getRoot()) << endl;cout << "level height of tree: " << btree.level_get_height(btree.getRoot()) << endl;cout << "stack height of tree: " << btree.stack_get_height(btree.getRoot()) << endl;btree.destory_tree(btree.getRoot());return 0; }


3.2 基于數(shù)組的二叉樹(shù)實(shí)現(xiàn)代碼

/*** @description: 二叉樹(shù),數(shù)組實(shí)現(xiàn)* @author: michael ming* @date: 2019/5/11 11:44* @modified by: */ #include <iostream> using namespace std; template <class T> struct node {T data;node<T>(){} }; template <class T> class binary_tree { private:int size;size_t tree_arrlen;node<T>* tree; public:binary_tree(int len = 20):size(len),tree_arrlen(0){tree = new node<T> [size];}~binary_tree(){delete [] tree;}void insert(T &data){if(tree_arrlen < size)tree[++tree_arrlen].data = data;}void preOrderPrint(size_t index = 1){if(tree_arrlen < 1 || index > tree_arrlen)return;cout << tree[index].data << " ";preOrderPrint(index*2);preOrderPrint(index*2+1);}void inOrderPrint(size_t index = 1){if(tree_arrlen < 1 || index > tree_arrlen)return;inOrderPrint(index*2);cout << tree[index].data << " ";inOrderPrint(index*2+1);}void postOrderPrint(size_t index = 1){if(tree_arrlen < 1 || index > tree_arrlen)return;postOrderPrint(index*2);postOrderPrint(index*2+1);cout << tree[index].data << " ";} };int main() {binary_tree<int> btree;for(int i = 1; i < 8; ++i)btree.insert(i);btree.preOrderPrint();cout << endl;btree.inOrderPrint();cout << endl;btree.postOrderPrint();return 0; }

3.3 非遞歸法 二叉樹(shù)遍歷

  • 前序(入棧root,訪問(wèn)stack.top(), 出棧,依次入棧節(jié)點(diǎn),節(jié)點(diǎn))
void stackPreOrder() {stack<node<T>*> nodeStack;node<T> * nodep = root;if(nodep != NULL){nodeStack.push(nodep);while(!nodeStack.empty()){nodep = nodeStack.top();nodeStack.pop();cout << nodep->data << " ";if(nodep->right != NULL) //注意左右節(jié)點(diǎn)入棧順序!!!nodeStack.push(nodep->right);if(nodep->left != NULL)nodeStack.push(nodep->left);}} }
  • 中序(入棧右、根、(左的右、左的根、…),左右節(jié)點(diǎn)為空,到達(dá)葉子節(jié)點(diǎn),打印葉子節(jié)點(diǎn),)
void stackInOrder() {stack<node<T>*> nodeStack;node<T> *nodep = root;while(nodep != NULL){while(nodep != NULL)//入棧右、根{if(nodep->right)nodeStack.push(nodep->right);nodeStack.push(nodep);nodep = nodep->left;}nodep = nodeStack.top();//根節(jié)點(diǎn)nodeStack.pop();while(!nodeStack.empty() && nodep->right == NULL)//nodep為葉子節(jié)點(diǎn){cout << nodep->data << " ";//打印葉子節(jié)點(diǎn)nodep = nodeStack.top();nodeStack.pop();}cout << nodep->data << " ";//左節(jié)點(diǎn)為空,右節(jié)點(diǎn)非空or最后一個(gè)節(jié)點(diǎn)if(!nodeStack.empty()){nodep = nodeStack.top();nodeStack.pop();}elsenodep = NULL;} }
  • 后序
void stackPostOrder() {stack<node<T>*> nodeStack;node<T> *nodep = root, *temp = root;while(nodep != NULL){for(;nodep->left != NULL; nodep = nodep->left)nodeStack.push(nodep); //入棧一路上的左節(jié)點(diǎn)while(nodep->right == NULL || nodep->right == temp){cout << nodep->data << " ";//打印葉子節(jié)點(diǎn)temp = nodep;if(nodeStack.empty())return;nodep = nodeStack.top();//回到父節(jié)點(diǎn)nodeStack.pop();}nodeStack.push(nodep);nodep = nodep->right;//轉(zhuǎn)到右子樹(shù)} }

完整代碼

總結(jié)

以上是生活随笔為你收集整理的数据结构--二叉树 Binary Tree的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。