1. 程式人生 > >二叉樹的基本操作以及相關問題的求解—C++實現

二叉樹的基本操作以及相關問題的求解—C++實現

二叉樹

二叉樹是重要的資料結構,在學習中以及考試、面試中不可避免的考點,現在我就把有關二叉樹的操作用C++總結 一下,可能有些同學使用的是C語言,但是無論C語言還是c++,對於二叉樹的操作方法都是一樣的,之後,我也會抽空給出C語言的實現。

本次實現是在vs2008的一個整合開發環境,為了增強程式碼的複用性,此次編寫使用了模版,關於模版可以參考的我的另外一篇部落格:http://blog.csdn.net/dy_1024/article/details/78643644,如果大家在使用的時候,不實用模版,只需把程式碼中的模版型別T,換成你需要的型別即可。

首先我們用結構體給出二叉樹結點的結構:

template<class T>//如果大家不使用模版的話,把這行程式碼去掉,將結構體中的T該成你需要的型別即可
struct BinTreeNode{
	BinTreeNode(const T& data):_left(NULL),_right(NULL),_data(data){}//二叉樹結點的建構函式,方便之後給出新結點
	BinTreeNode* _right;//右子樹
	BinTreeNode* _left;//左子樹
	T _data;//資料域
};
因為使用c++,所以我們將二叉樹封裝成一個二叉樹類,進行管理,同樣使用模版:
template<class T>
class  BinTree
{
	typedef BinTreeNode<T> Node;//將之前的類此重定義,方便以後的使用
	typedef Node* PNode;
public:
	BinTree():_pRoot(NULL){}
	//建構函式裡面使用的建立二叉樹的函式,
	void _CreatBinTree(PNode& pRoot,const T* array,size_t size,size_t& index,const T& invalid)
	{
		if(index<size && array[index] != invalid)
		{
			pRoot = new Node(array[index]);
			_CreatBinTree(pRoot->_left,array,size,++index,invalid);
			_CreatBinTree(pRoot->_right,array,size,++index,invalid);
		}
	}
	
//建構函式,在給建構函式傳參的時候,我們定義:char *array ="ABD###CE##F",這是二叉樹前序遍歷的結果,"#"代表無效值,也就是空子樹 BinTree(const T* array,size_t size,const T& invalid) { size_t index = 0; _CreatBinTree(_pRoot,array,size,index,invalid);//我們將二叉樹的構造封裝成函式,這樣結構比較明確 } //前序遍歷 void _PreOrder(PNode pRoot) { if(pRoot) { cout<<pRoot->_data<<" "; _PreOrder(pRoot->_left); _PreOrder(pRoot->_right); } }
//中序遍歷 void _InOrder(PNode pRoot) { if(pRoot) { _InOrder(pRoot->_left); cout<<pRoot->_data<<" "; _InOrder(pRoot->_right); } } //後續遍歷 void _PostOrder(PNode pRoot) { if(pRoot) { _PostOrder(pRoot->_left); _PostOrder(pRoot->_right); cout<<pRoot->_data<<" "; } } //拷貝建構函式裡面需要的拷貝函式 PNode _CopyBinTree(PNode pRoot) { PNode pNewNode = NULL; if(pRoot) { pNewNode = new Node(pRoot->_data); pNewNode->_left = _CopyBinTree(pRoot->_left); pNewNode->_right = _CopyBinTree(pRoot->_right); } return pNewNode; } BinTree(const BinTree<T>& bt)//拷貝建構函式 { _pRoot = _CopyBinTree(bt._pRoot); } //銷燬函式 void _DestoryBinTree(PNode& pRoot) { if(pRoot) { _DestoryBinTree(pRoot->_left); _DestoryBinTree(pRoot->_right); } delete pRoot; pRoot = NULL; } //賦值運算子過載 BinTree<T>& operator=(const BinTree<T>& bt) { //把原有的樹銷燬掉,在用拷貝函式,拷貝一個新樹 _DestoryBinTree(_pRoot); _pRoot = _CopyBinTree(bt._pRoot); return *this; } //求樹的高度 size_t _Height(PNode pRoot) { if(NULL == pRoot) return 0; if(pRoot->_left == NULL && pRoot->_right == NULL) { return 1; } size_t left = _Height(pRoot->_left);//將左子樹的高度賦值給left size_t right = _Height(pRoot->_right);//將右子樹的高度賦值給right return left>right?(left+1):(right+1);比較左右子樹的大小,大的再加上1,就是樹的大小 } //求按層遍歷的個數,思路:當你要求第3層的時候,如果以第二層為根,那麼就是求第二層的結點,依次遍歷 size_t _GetKLevelNodeCount(PNode pRoot,size_t k) { if(k == 0 || NULL == pRoot)return 0; if(k == 1)return 1; return _GetKLevelNodeCount(pRoot->_left,k-1)+_GetKLevelNodeCount(pRoot->_right,k-1); } //按層遍歷,我們使用佇列結構儲存每次收集的結點,運用佇列隊頭出隊尾進的特點,輸出每一層的結點 void _LevelOrder(PNode pRoot) { PNode pCur = NULL; queue<PNode> q; q.push(pRoot); while (!q.empty()) { pCur = q.front(); cout<<pCur->_data<<" "; if(pCur->_left) q.push(pCur->_left); if(pCur->_right) q.push(pCur->_right); q.pop(); } } //判斷結點是否在樹中 bool _IsNodeInBinTree(PNode pRoot,PNode pNode) { if(NULL == pRoot || pNode == NULL) return false; if(pRoot == pNode) return true; bool Isflag = _IsNodeInBinTree(pRoot->_left,pNode); if(Isflag) return true; return _IsNodeInBinTree(pRoot->_right,pNode); } //在樹種找到一個結點 PNode _Find(PNode pRoot,const T& data) { if(NULL == pRoot) return NULL; if(pRoot->_data == data) return pRoot; PNode pCur = NULL; if(pCur = _Find(pRoot->_left,data)) return pCur; return _Find(pRoot->_right,data); } //求樹的映象—遞迴 void _Mirror(PNode pRoot) { swap(pRoot->_left, pRoot->_right);//直接交換左右子樹裡面的地址,那麼他的左右子樹就交換成功了 if(pRoot->_left) _Mirror(pRoot->_left); if(pRoot->_right) _Mirror(pRoot->_right); } //求樹得映象-非遞迴 void _Mirror_nor(PNode pRoot) { if(NULL == pRoot) return; queue<PNode> q; q.push(pRoot); while (!q.empty()) { PNode pCur = q.front(); swap(pCur->_left,pCur->_right); if(pCur->_left) q.push(pCur->_left); if(pCur->_right) q.push(pCur->_right); q.pop(); } } //判斷一棵二叉樹是不是一顆完全二叉樹,當我們發現一個結點只有左子樹,沒有右子樹的時候,就要開始判斷
//下一個結點有沒有子樹,如果有就不是,如果沒有就繼續,和層序遍歷一樣,使用佇列結構
bool _IsCompleteBinTree(PNode pRoot){if(NULL == pRoot)return true;queue<PNode> q;q.push(pRoot);bool Isflag = false;while (!q.empty()){PNode pCur = q.front();if(Isflag){if(pCur->_left || pCur->_right)return false;}if(pCur->_left && pCur->_right){q.push(pCur->_left);q.push(pCur->_right);}else if(pCur->_left){q.push(pCur->_left);Isflag = true;}else if(pCur->_right){return false;}else {return true;}q.pop();}return false;}//前序遍歷—非遞迴(利用棧的特點,只能棧頂出入,來遍歷二叉樹)void _PreOrder_nor(PNode pRoot){if(NULL == pRoot)return ;stack<PNode> s;s.push(pRoot);while (!s.empty()){PNode pCur = s.top();s.pop();cout<<pCur->_data<<" ";if(pCur->_right)s.push(pCur->_right);if(pCur->_left)s.push(pCur->_left);}}//介面,(因為是在類裡面封裝,所以封裝介面之後,就可以不用給函式傳參,更加簡潔)void PreOrder_nor(){cout<<"PreOrder_nor: "<<endl;_PreOrder_nor(_pRoot);cout<<endl;}bool IsCompleteBinTree(){return _IsCompleteBinTree(_pRoot);}void Mirror_nor(){_Mirror_nor(_pRoot);}void Mirror(){_Mirror(_pRoot);}bool IsNodeInBinTree(PNode pNode){return _IsNodeInBinTree(_pRoot,pNode);}PNode Find(const T& data){return _Find(_pRoot,data);}void GetKLevelNodeCount(size_t k){cout<<"第"<<k<<"層結點個數是:";cout<<_GetKLevelNodeCount(_pRoot,k)<<endl;}void LevelOrder(){cout<<"LevelOrder: ";_LevelOrder(_pRoot);cout<<endl;}void Height(){cout<<"Height: ";cout<<_Height(_pRoot)<<endl;}void PreOrder(){cout<<"PreOrder: ";_PreOrder(_pRoot);cout<<endl;}void InOrder(){cout<<"InOrder: ";_InOrder(_pRoot);cout<<endl;}void PostOrder(){cout<<"PostOrder: ";_PostOrder(_pRoot);cout<<endl;}private:PNode _pRoot;};


限於編者水平,本文文章難免有缺漏之處,歡迎指正

Tip:如需轉載,請註明出處

相關推薦

C語言-基本操作以及搜尋基本操作

功能 二叉樹操作: 建立二叉樹 遍歷二叉樹(前序,中序,後續) 計算高度 計算結點數目 清空二叉樹 空樹判斷 二叉搜尋樹操作: 插入 最值(最大值,最小值) 刪除 程式碼 #include &l

基本操作

arch 非遞歸 alt pro stack depth 隊列 步驟 read 廣度優先搜索 1、把根節點入隊列; 2、如果隊列非空,出隊,再依次將左子樹入隊、右子樹入隊; 3、重復步驟2,直到隊列為空。 void BreadFirstSearch(TreeNode *ro

線索基本操作實現

2018-11-18-18:25:23 一:二叉樹 1.二叉樹的性質   ①:在二叉樹的第i層上至多有pow(2,i-1)個結點(i>=1)。   ②:深度為k的二叉樹至多有pow(2,k)-1個結點(k>=1)。   ③:對任何一顆二叉樹T,如果其終端結點的個數為n0,度為2的結點數為

【資料結構】基本操作

文章目錄 BinaryTree.h BinaryTree.c Test.c 棧和佇列的相關函式: 棧:https://blog.csdn.net/weixin_41892460/article/details/82

c++學習筆記—基本操作實現

用c++語言實現的二叉樹基本操作,包括二叉樹的建立、二叉樹的遍歷(包括前序、中序、後序遞迴和非遞迴演算法)、求二叉樹高度,計數葉子節點數、計數度為1的節點數等基本操作。 IDE:vs2013 具體實現程式碼如下: #include "stdafx.h" #include

超全C語言基本操作及講解

今天刷LeetCode上的題的時候,做到了關於二叉樹的題,於是決定把這一塊的知識整理一下。1、二叉樹的定義二叉樹通常以結構體的形式定義,如下,結構體內容包括三部分:本節點所儲存的值、左孩子節點的指標、右孩子節點的指標。這裡需要注意,子節點必須使用指標,就像我們定義結構體連結串

實驗四 基本操作實現

實現鏈式儲存建立,遞迴先序 中序 後序遍歷,葉子結點數,數的結點總數,交換左右子樹 #include <stdio.h> #include <stdlib.h> #include <malloc.h> int cnt; //結點宣告,資

基本操作實現及總結(適合複習)

本文包含以下內容 1 ,二叉樹三種建立 前序遞迴 表示式非遞迴 孩子兄弟表示式非遞迴 2,遍歷 三種遍歷的遞迴與非遞迴實現(前中後序) 層次遍歷(普通二叉樹,孩子兄弟連結串列)

的各種遍歷演算法C++實現

大概在網上摘抄和總結了二叉樹的幾種遍歷方法,有遞迴和非遞迴的,先貼在這裡,用的時候在來看看。再次謝謝網上的各種資源。謝謝CSDN博主SJF0115,謝謝劍指offer作者何海濤~ #include"stdafx.h" #include<iostream>

非遞迴遍歷c++實現

三種遍歷演算法均採用棧來實現 1.前序遍歷:先訪問根節點,再訪問左子樹,最後訪問右子樹 先將根節點進棧,棧不空時迴圈:{出棧tmp,訪問tmp,若其右子樹節點不空則將tmp的右孩子節點進棧,若其左孩子節點不空則將tmp的左孩子節點進棧。} 2.中序遍歷演算法:左中右 從根節

基本操作以及相關問題的求解C++實現

二叉樹 二叉樹是重要的資料結構,在學習中以及考試、面試中不可避免的考點,現在我就把有關二叉樹的操作用C++總結 一下,可能有些同學使用的是C語言,但是無論C語言還是c++,對於二叉樹的操作方法都是一樣的,之後,我也會抽空給出C語言的實現。 本次實現是在vs2008的一個整合

的建立以及三種遍歷操作

      由二叉樹結點的性質可以確定的是,二叉樹結構相比普通的連結串列結點而複雜,需要通過其左/右指標訪問其左/右子樹結點。而在熟悉了二叉樹的結構後,需要注意的是二叉樹的建立以及遍歷操作。而建立與遍歷兩種操作,需要利用的是遞迴的思想,即保持每一個子集函式操作與其父函式相同。

【資料結構】平衡的構建以及增加刪除操作

一、前言       最近學習中遇到了平衡二叉樹的實用,要求是對一個數據列,進行平衡二叉樹的排列,並畫出結果,小編剛開始的時候不是很會,通過總結資料學習了一下平衡二叉樹的相關知識,通過部落格總結一下。

實驗三:操作(結構轉換,遞迴和非遞迴的先序、中序和後序遍歷,以及層次遍歷,葉子結點和總結點的計數)

(1)將一棵二叉樹的所有結點儲存在一維陣列中,虛結點用#表示,利用二叉樹性質5,建立二叉樹的二叉連結串列。 (2) 寫出對用二叉連結串列儲存的二叉樹進行先序、中序和後序遍歷的遞迴和非遞迴演算法。 (3)寫出對用二叉連結串列儲存的二叉樹進行層次遍歷演算法。 (4)求二叉樹

的建立及相關操作

二叉樹是一種非常重要的資料儲存結構,是一種特殊的、常用的樹型資料結構,則其基本操作也就非常重要。因為二叉樹本身就是一個遞迴型資料儲存結構,所以其操作基本上都可以用遞迴的形式實現。 【二叉樹的建立】 要嚴格地進行輸入,要把所有結點的左右孩子都進行輸入,空結點用#代替(比如:ABC##DE#G#

資料結構--的建立和相關操作

下面給出兩個關於二叉樹的題目: 1.編寫程式任意輸入二叉樹的結點個數和結點值,構造一棵二叉樹,採用三種遞迴遍歷演算法(前序、中序、後序)對這棵二叉樹進行遍歷並計算出二叉樹的高度。 2 .編寫程式生成下面所示的二叉樹,並採用先序遍歷的非遞迴演算法對此二叉樹進行遍歷。  

基本演算法,遞迴非遞迴遍歷以及求高度、寬度等

二叉樹基本演算法,遍歷以及求高度、寬度等路徑 轉自Powered by: C++部落格   Copyright © 天一程 //二叉樹的相關演算法,《資料結構習題與解析》7.3 //演算法 49個,程式碼量1200+ ,時間9小時 #include<

java實現的構建以及3種遍歷方法

輸出 for () 如果 順序 bintree 參考 oca gpl 轉載自http://ocaicai.iteye.com/blog/1047397 大二下學期學習數據結構的時候用C介紹過二叉樹,但是當時熱衷於java就沒有怎麽鳥二叉樹,但是對二叉樹的構建及遍歷一

基本概念

相同 完全二叉樹 算法 平衡 都在 最大值 fma word 特殊 1. 高度:樹T所有節點深度的最大值,節點V對應子樹高度為該節點的高度,根節點高度為整棵樹的高度 2.深度:節點V到根節點R的唯一路徑所經過的數目稱為V的深度 3.huffman編碼:構造出的帶權平均深

基礎操作

rep unsigned signed ace 輸出 nod inf dtree bit #include<bits/stdc++.h> #define de(x) cout<<#x<<"="<<x<<endl;