1. 程式人生 > 其它 >C++二叉樹探究

C++二叉樹探究

本文將對C++二叉樹進行分析和程式碼實現。

定義

樹(Tree)是n(n>=0)個結點的有限集。n=0時稱為空樹。在任意一顆非空樹中:

1)有且僅有一個特定的稱為根(Root)的結點;

2)當n>1時,其餘結點可分為m(m>0)個互不相交的有限集T1、T2、......、Tn,其中每一個集合本身又是一棵樹,並且稱為根的子樹。

此外,樹的定義還需要強調以下兩點:

1)n>0時根結點是唯一的,不可能存在多個根結點,資料結構中的樹只能有一個根結點。

2)m>0時,子樹的個數沒有限制,但它們一定是互不相交的。

結點的度

結點擁有子樹數目稱為節點的度。

結點關係

結點子樹的根結點為該結點的孩子結點

。相應該結點稱為孩子結點的雙親結點

在上圖中,A為B的雙親結點,B為A的孩子結點。

同一個雙親結點的孩子結點之間互稱兄弟結點

在上圖中,結點B與結點C互為兄弟結點。

結點層次

從根開始定義起,根為第一層,根的孩子為第二層,以此類推。

二叉樹定義

二叉樹:是n(n>=0)個結點的有限集合,該集合或者為空集(稱為空二叉樹),或者由一個根結點和兩棵互不相交的、分別稱為根結點的左子樹和右子樹的二叉樹組成。

如下圖就是一個二叉樹:

二叉樹特點

二叉樹的特點有:

  • 每個結點最多兩個子樹,所以二叉樹中不存在度大於2的結點。注意不是隻有兩棵子樹,而是最多有。沒有子樹或者有一棵子樹都是可以的。
  • 左子樹和右子樹是有順序的,次序布恩那個任意顛倒。
  • 即使樹中的某結點只有一棵子樹,也要區分它是左子樹還是右子樹。如圖:樹1和樹2是同一棵樹,但卻是不同的二叉樹。

二叉樹具有五種基本形態:

空二叉樹;

只有一個根結點;

根結點只有左子樹;

根結點只有右子樹;

根結點既有左子樹又有右子樹。

特殊二叉樹

再來介紹一些特殊的二叉樹。

斜樹

顧名思義,斜樹一定是斜的,但是往那邊斜還是有講究的。

所有的結點都只有左子樹的二叉樹叫左斜樹,所有結點都是隻有右子樹的二叉樹叫右斜樹。兩種統稱為斜樹。

下面兩個圖分別就是左斜樹和右斜樹:

滿二叉樹

蘇東坡有詩云:人有悲歡離合,月有陰晴圓缺,此事古難全。意思就是完美是理想,不完美才是人生。

我們通常看到的例子全是左高右低、參差不齊的二叉樹,是否有完美的二叉樹呢。

在一棵二叉樹中,如果所有分支結點都存在左子樹和右子樹,並且所有的葉子結點都在同一層上,這樣的二叉樹叫做滿二叉樹。如圖

單單是每個結點都有左右子樹,不能算是滿二叉樹,還必須要所有的葉子結點都處在同一層,這樣就做到了二叉樹的平衡。因此滿二叉樹的特點有:

  1. 葉子只能出現在最下面一層,出現在其他層就不能達到平衡;
  2. 非葉子結點的度一定是2;
  3. 同樣深度的二叉樹中,滿二叉樹的結點個數最多,葉子樹最多。

完全二叉樹

對一棵具有n個結點的二叉樹按層序編號,如果編號為i(1<=i<=n)的結點與同樣深度的滿二叉樹中編號為i的結點在二叉樹中位置完全相同,則這棵二叉樹稱為完全二叉樹。如圖:

首先要從字面上區分,“完全”和“滿”的差異,滿二叉樹一定是完全二叉樹,完全二叉樹不一定是滿的。

注意完全二叉樹中的編號與滿二叉樹中的相同,而且編號全部連續,有斷開的就不是完全二叉樹,如下圖中的三棵樹都不是完全二叉樹。

完全二叉樹的特點:

  1. 葉子結點只能出現在最下面兩層;
  2. 最下層的葉子一定集中在左部連續位置;
  3. 倒數二層,若有葉子結點,一定都在右部連續位置;
  4. 如果結點的度為1,則該結點只有左孩子,即不存在只有右子樹的情況;
  5. 同樣結點數的二叉樹,完全二叉樹深度最小。

我們也得出一個判斷某二叉樹是否是完全二叉樹的方法,那就是看著樹的示意圖,心中默默給每個結點按照滿二叉樹的結構逐層順序編號,如果編號出現空擋,就說明不是完全二叉樹,否則就是。

二叉樹的性質

二叉樹性質1

在二叉樹的第i層上至多有2i-1個結點(i>=1)。

上圖中: 第1層: 1個: 21-1=20=1 第2層: 1個: 22-1=21=2 第3層: 1個: 23-1=22=4 第4層: 8個: 24-1=23=8

通過資料歸納法,很容易得出在二叉樹的第i層上最多有 2i-1個結點。

二叉樹性質2

深度為k的二叉樹最多有2k-1個結點(k>=1)。

這裡注意是2的k次冪再減1。

如果有一層,最多1=21-1個結點 如果有兩層,最多1+2=22-1個結點 如果有三層,最多1+2+4=23-1個結點 如果有四層,最多1+2+4+8=24-1個結點

通過資料歸納法的論證,可以得出如果有k層,結點數最多為2k-1。

二叉樹性質3

對任何一棵二叉樹T,如果其終端結點數為n0,度為2的結點數為n2,則n0=n2+1

終端結點就是葉子結點,而一棵二叉樹,除了葉子結點外,剩下的就是度為1和2的結點了,設n1是度為1的結點數。則樹T的結點總數就是n=n0+n1+n2。

我們換個角度,再數一數連線線,由於根結點只有分支出去,沒有分支進入,所以分支線總數為結點總數減去1,n-1=n1+2n2,又因為n=n0+n1+n2,得出n0=n2+1 。

二叉樹性質4

具有n個結點的完全二叉樹的深度為不大於log2n的最大整數+1 。

這裡不再詳細推導。

二叉樹性質5

如果對一棵有n個結點的完全二叉樹的結點按層序編號(從第一層到最後一層,每層從左到右),對任一結點i(1<=i<=n)有:

  1. 如果i=1,則結點i是二叉樹的根,無雙親;如果i>1,則其雙親是結點 ⌊ i/2 ⌋ 。
  2. 如果2i>n,則結點i無左孩子(結點i為葉子結點);否則其左孩子是結點2i 。
  3. 如果2i+1>n,則結點i無右孩子;否則其右孩子是結點2i+1 。

二叉樹的儲存結構

順序儲存

二叉樹的順序儲存結構就是使用一維陣列儲存二叉樹中的結點,並且結點的儲存位置,就是陣列的下標索引。

如圖所示的一棵完全二叉樹採用順序儲存方式,如圖表示:

由圖可以看出,當二叉樹為完全二叉樹時,結點數剛好填滿陣列。
那麼當二叉樹不為完全二叉樹時,採用順序儲存形式如何呢?例如:對於上圖描述的二叉樹:

其中淺色結點表示結點不存在。那麼上圖所示的二叉樹的順序儲存結構如圖所示:

其中,∧表示陣列中此位置沒有儲存結點。此時可以發現,順序儲存結構中已經出現了空間浪費的情況。
那麼對於右斜樹極端情況對應的順序儲存結構如圖所示:

由圖可以看出,對於這種右斜樹極端情況,採用順序儲存的方式是十分浪費空間的。因此,順序儲存一般適用於完全二叉樹。

二叉樹高度

二叉樹遍歷

前序遍歷(根 左 右):G D A F E M H Z

中序遍歷(左 根 右):A D E F G H M Z

後序遍歷(左 右 根):A E F D H Z M G

層次遍歷(依次往下):G D M A F H Z E

定義

二叉樹的遍歷是指從二叉樹的根結點出發,按照某種次序依次訪問二叉樹中的所有結點,使得每個結點被訪問一次,且僅被訪問一次。
二叉樹的訪問次序可以分為四種:

前序遍歷
中序遍歷
後序遍歷
層序遍歷

前序遍歷

前序遍歷通俗的說就是從二叉樹的根結點出發,當第一次到達結點時就輸出結點資料,按照先向左在向右的方向訪問。

如圖所示二叉樹訪問如下:

從根結點出發,則第一次到達結點A,故輸出A;

繼續向左訪問,第一次訪問結點B,故輸出B;

按照同樣規則,輸出D,輸出H;

當到達葉子結點H,返回到D,此時已經是第二次到達D,故不在輸出D,進而向D右子樹訪問,D右子樹不為空,則訪問至I,第一次到達I,則輸出I;

I為葉子結點,則返回到D,D左右子樹已經訪問完畢,則返回到B,進而到B右子樹,第一次到達E,故輸出E;

向E左子樹,故輸出J;

按照同樣的訪問規則,繼續輸出C、F、G;

則圖所示二叉樹的前序遍歷輸出為:
ABDHIEJCFG

中序遍歷

中序遍歷就是從二叉樹的根結點出發,當第二次到達結點時就輸出結點資料,按照先向左在向右的方向訪問。

如圖所示二叉樹中序訪問如下:

從根結點出發,則第一次到達結點A,不輸出A,繼續向左訪問,第一次訪問結點B,不輸出B;繼續到達D,H;

到達H,H左子樹為空,則返回到H,此時第二次訪問H,故輸出H;

H右子樹為空,則返回至D,此時第二次到達D,故輸出D;

由D返回至B,第二次到達B,故輸出B;

按照同樣規則繼續訪問,輸出J、E、A、F、C、G;

則如圖所示二叉樹的中序遍歷輸出為:
HDIBJEAFCG

後序遍歷

後序遍歷就是從二叉樹的根結點出發,當第三次到達結點時就輸出結點資料,按照先向左在向右的方向訪問。

圖3.13所示二叉樹後序訪問如下:

從根結點出發,則第一次到達結點A,不輸出A,繼續向左訪問,第一次訪問結點B,不輸出B;繼續到達D,H;
到達H,H左子樹為空,則返回到H,此時第二次訪問H,不輸出H;

H右子樹為空,則返回至H,此時第三次到達H,故輸出H;

由H返回至D,第二次到達D,不輸出D;

繼續訪問至I,I左右子樹均為空,故第三次訪問I時,輸出I;

返回至D,此時第三次到達D,故輸出D;

按照同樣規則繼續訪問,輸出J、E、B、F、G、C,A;

則圖3.13所示二叉樹的後序遍歷輸出為:
HIDJEBFGCA

雖然二叉樹的遍歷過程看似繁瑣,但是由於二叉樹是一種遞迴定義的結構,故採用遞迴方式遍歷二叉樹的程式碼十分簡單。

二叉樹程式碼實現

首先定義一個二叉樹,程式碼如下:

	Monster m1(1,1,"刺蝟");							
	Monster m2(2,2,"野狼");							
	Monster m3(3,3,"野豬");							
	Monster m4(4,4,"士兵");							
	Monster m5(5,5,"火龍");							
	Monster m6(6,6,"獨角獸");							
	Monster m7(7,7,"江湖大盜");							
								
								
	TreeNode<Monster>* n1 = new TreeNode<Monster>(m1);							
	TreeNode<Monster>* n2 = new TreeNode<Monster>(m2);							
	TreeNode<Monster>* n3 = new TreeNode<Monster>(m3);							
	TreeNode<Monster>* n4 = new TreeNode<Monster>(m4);							
	TreeNode<Monster>* n5 = new TreeNode<Monster>(m5);							
	TreeNode<Monster>* n6 = new TreeNode<Monster>(m6);							
	TreeNode<Monster>* n7 = new TreeNode<Monster>(m7);							
								
	m_pRoot = n5;							
	n5->pLeft = n4;							
	n5->pRight = n6;							
	n4->pLeft = n1;							
	n1->pRight = n2;							
	n6->pLeft = n3;							
	n3->pRight = n7;							
	size = 7;

二叉樹的圖示如下:

這裡進入反彙編跟一下二叉樹的地址儲存,首先找到m_pRoot的地址為3709A0

跟進去檢視,發現左子樹所在的地址為370938,右子樹所在的地址為370A08,這裡我繼續跟左子樹往下走

左子樹所在的地址為370800,無右子樹所以為000000

繼續往下跟,無左子樹所以為000000,右子樹所在的地址為370868

繼續往下跟,因為到2這個地方左子樹和右子樹都沒有了,所以地址都為000000

這裡首先實現中序遍歷,這裡通過上面的反彙編可以發現pName即怪物名字是在序號的8個位元組之後

執行效果如下

二叉樹的圖示如下:

前序:5412637

中序:1245376

後序:2147365

前序實現

中序實現

後序實現

完整程式碼如下

// cplus二叉樹.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <Windows.h>

class Monster								
{								
public:								
	int ID;							
	int Level;							
	char Name[20];							
public:								
	Monster(){}							
	Monster(int ID,int Level,char* Name)							
	{							
		this->ID = ID;						
		this->Level = Level;						
		memcpy(&this->Name,Name,strlen(Name)+1);						
	}							
};								
								
template<class T>								
class TreeNode{								
public:								
	T element;					//當前節點儲存的資料		
	TreeNode<T>* pLeft;					//指向左子節點的指標		
	TreeNode<T>* pRight;					//指向右子節點的指標		
								
	TreeNode(T& ele){							
		//初始化Node節點						
		memset(&element,0,sizeof(TreeNode));						
		//為元素賦值						
		memcpy(&element,&ele,sizeof(T));						
		pLeft = pRight = NULL;						
	}							
};								
								
template<class T>								
class BSortTree{								
public:								
	BSortTree();					//建構函式		
	~BSortTree();					//解構函式		
public:								
	void InOrderTraverse(TreeNode<T>* pNode);					//中序遍歷		
	void PreOrderTraverse(TreeNode<T>* pNode);					//前序遍歷		
	void PostOrderTraverse(TreeNode<T>* pNode);					//後序遍歷		
	TreeNode<T>* GetRoot();					//返回根節點		
	int GetDepth(TreeNode<T>* pNode);					//返回某個節點的高度/深度		
private:								
	void Init();
	void Clear(IN TreeNode<T>* pNode);    //清理二叉樹
private:								
	TreeNode<T>* m_pRoot;					//根結點指標		
	int size;					//樹中元素總個數		
};								
								
template<class T> 								
BSortTree<T>::BSortTree()								
{								
	Init();							
}								
template<class T> 								
BSortTree<T>::~BSortTree()    //釋放所有節點空間
{								
	printf("The destructor has been executed!\n\n");
	Clear(m_pRoot);						
								
}								
								
template<class T> 								
void BSortTree<T>::Init()								
{								
								
	Monster m1(1,1,"刺蝟");							
	Monster m2(2,2,"野狼");							
	Monster m3(3,3,"野豬");							
	Monster m4(4,4,"士兵");							
	Monster m5(5,5,"火龍");							
	Monster m6(6,6,"獨角獸");							
	Monster m7(7,7,"江湖大盜");							
								
								
	TreeNode<Monster>* n1 = new TreeNode<Monster>(m1);							
	TreeNode<Monster>* n2 = new TreeNode<Monster>(m2);							
	TreeNode<Monster>* n3 = new TreeNode<Monster>(m3);							
	TreeNode<Monster>* n4 = new TreeNode<Monster>(m4);							
	TreeNode<Monster>* n5 = new TreeNode<Monster>(m5);							
	TreeNode<Monster>* n6 = new TreeNode<Monster>(m6);							
	TreeNode<Monster>* n7 = new TreeNode<Monster>(m7);							
								
	m_pRoot = n5;							
	n5->pLeft = n4;							
	n5->pRight = n6;							
	n4->pLeft = n1;							
	n1->pRight = n2;							
	n6->pLeft = n3;							
	n3->pRight = n7;							
	size = 7;							
	/*							
					  5			
								
				4		    6		
								
			1		    3			
								
			     2		       7			
								
	*/							
}	

template<class T>
void BSortTree<T>::Clear(TreeNode<T>* pNode)
{
	if( pNode != NULL )
	{
		Clear(pNode->pLeft);
		Clear(pNode->pRight);
		delete pNode;
		pNode = NULL;
	}
}
							
template<class T> 								
TreeNode<T>* BSortTree<T>::GetRoot()								
{								
	return m_pRoot;							
}								
template<class T>								
int BSortTree<T>::GetDepth(TreeNode<T>* pNode)								
{								
    if(pNode==NULL) 								
    {								
	return 0;  							
    }								
    else  								
    {  								
        int m = GetDepth(pNode->pLeft);  								
        int n = GetDepth(pNode->pRight);  								
        return (m > n) ? (m+1) : (n+1);   								
    }  								
}								
template<class T> 								
void BSortTree<T>::InOrderTraverse(TreeNode<T>* pNode)    //中序遍歷所有怪物,列出怪的名字(左 根 右)							
{
	char* pName = NULL;

	if (pNode != NULL)
	{
		InOrderTraverse(pNode->pLeft);
		pName = (char*)&pNode->element;
		pName = pName + 8; 

		printf("Use InOrderTraverse,the value is:%d\n",pNode->element);
		printf("Use InOrderTraverse,the name is:%s\n",pName);

		InOrderTraverse(pNode->pRight);
	}
														
}								
								
template<class T> 								
void BSortTree<T>::PreOrderTraverse(TreeNode<T>* pNode)    //前序遍歷所有怪物,列出怪的名字(根 左 右)						
{	
	char* pName = NULL;

	if (pNode != NULL)
	{
		pName = (char*)&pNode->element;
		pName = pName + 8; 

		printf("Use PreOrderTraverse,the value is:%d\n",pNode->element);
		printf("Use PreOrderTraverse,the name is:%s\n",pName);

		PreOrderTraverse(pNode->pLeft);
		PreOrderTraverse(pNode->pRight);
	}
								
								
}								
								
template<class T> 								
void BSortTree<T>::PostOrderTraverse(TreeNode<T>* pNode)    //後序遍歷所有怪物,列出怪的名字(左 右 根)								
{	
	char* pName = NULL;

	if (pNode != NULL)
	{
		pName = (char*)&pNode->element;
		pName = pName + 8; 

		PreOrderTraverse(pNode->pLeft);
		PreOrderTraverse(pNode->pRight);

		printf("Use PostOrderTraverse,the value is:%d\n",pNode->element);
		printf("Use PostOrderTraverse,the name is:%s\n",pName);
	}
								
								
}								
								

void TestSecondtree()
{
	
	BSortTree<Monster>* p = new BSortTree<Monster>;
	
	p->InOrderTraverse(p->GetRoot());

	p->PreOrderTraverse(p->GetRoot());

    p->PostOrderTraverse(p->GetRoot());
	
    delete p;
	

	
}

int main(int argc, char* argv[])
{
	TestSecondtree();

	return 0;
}

搜尋二叉樹/二叉排序樹

搜尋二叉樹/二叉排序樹的特點:

1、有很好的查詢效能

2、有很好的新增和刪除的效能

3、若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值

4、若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值

5、左、右子樹也分別為二叉排序樹

中序遍歷就能夠直接從小到大排列:3 5 6 7 10 12 13 15 16 18 20 23

搜尋二叉樹的刪除

情況1:葉子節點

1、刪除該節點

2、將父節點(左或者右)指標置NULL

情況2:只有一個子樹

1、刪除該節點

2、將父節點(左或者右)指標指向子樹

情況3:左右子樹都有

1、用右子樹最小的節點取代源節點

2、再遞迴刪除最小節點

搜尋二叉樹程式碼實現

寫於2021.6.15 22.22

明天歐洲盃,先溜了,德國打法國,法國沖沖衝!

1-0 小勝,但是沒看到好多進球有點可惜

首先測試一下輸出情況,no problem

完整程式碼如下主要是遍歷的思想

// cplus搜尋二叉樹.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <Windows.h>

#define SUCCESS           1 // 執行成功			
#define ERROR			 -1 // 執行失敗			         
						
template<class T>						
class TreeNode{						
public:						
	T element;					//當前節點儲存的資料
	TreeNode<T>* pLeft;					//指向左子節點的指標
	TreeNode<T>* pRight;					//指向右子節點的指標
	TreeNode<T>* pParent;					//指向父結點的指標
						
						
	TreeNode(T& ele){					
		//初始化Node節點				
		memset(&element,0,sizeof(TreeNode));				
		//為元素賦值				
		memcpy(&element,&ele,sizeof(T));				
		pLeft = pRight = pParent = NULL;				
	}					
	//過載== 比較兩結點是否相等					
	bool operator==(TreeNode<T>* node){ 					
		return node->element == element ? true : false;				
	}					
};						
						
template<class T>						
class BSortTree{						
public:						
	BSortTree();					
	~BSortTree();					
public:						
	bool IsEmpty();					
	DWORD Insert(T element);					
	void Delete(T element);					
	TreeNode<T>* Search(T element);					
	void InOrderTraverse(TreeNode<T>* pNode);					
	void PreOrderTraverse(TreeNode<T>* pNode);					
	void PostOrderTraverse(TreeNode<T>* pNode);					
private:						
	TreeNode<T>* GetMaxNode(TreeNode<T>* pNode);					
	TreeNode<T>* GetMinNode(TreeNode<T>* pNode);					
	TreeNode<T>* SearchNode(TreeNode<T>* pNode,T element);					
	DWORD InsertNode(T element, TreeNode<T>* pNode);					
	TreeNode<T>* DeleteNode(T element, TreeNode<T>* pNode);					
	void Clear(TreeNode<T>* pNode);					
private:						
	TreeNode<T>* m_pRoot;					
	int size;					
};						
						
template<class T> 						
BSortTree<T>::BSortTree()						
{						
	m_pRoot = NULL;					
	size = 0;					
}						
template<class T> 						
BSortTree<T>::~BSortTree(){						
						
	Clear(m_pRoot);					
}						
template<class T> 						
DWORD BSortTree<T>::Insert(T element)						
{						
	//如果根節點為空					
	if ( !m_pRoot )					
	{					
		m_pRoot = new TreeNode<T>(element);				
		size++;				
		return SUCCESS;				
	}					
	//如果根節點不為空					
	return InsertNode(element, m_pRoot);					
}						
template<class T> 						
DWORD BSortTree<T>::InsertNode(T element, TreeNode<T>* pNode)						
{						
	//將元素封裝到節點中					
	TreeNode<T>* pNewNode = new TreeNode<T>(element);
	
	//如果element == 當前節點 直接返回					
	if(element == pNode->element)					
	{					
		return SUCCESS;				
	}				
	
	//如果pNode的左子節點為NULL 並且element < 當前節點					
	if(pNode->pLeft == NULL && element < pNode->element)					
	{					
		pNode->pLeft = pNewNode;				
		pNewNode->pParent = pNode;				
		size++;				
		return SUCCESS;				
	}	
				
	//如果pNode的右子節點為NULL 並且element > 當前節點					
	if(pNode->pRight == NULL && element > pNode->element){					
		pNode->pRight = pNewNode;				
		pNewNode->pParent = pNode;				
		size++;				
		return SUCCESS;				
	}					
	//如果element<當前節點 且當前節點的左子樹不為空					
	if(element < pNode->element)					
	{					
		InsertNode(element,pNode->pLeft);				
	}					
	else					
	{					
		InsertNode(element,pNode->pRight);				
	}					
	return SUCCESS;					
}						
						
template<class T> 						
void BSortTree<T>::Clear(TreeNode<T>* pNode)						
{						
	if(pNode!=NULL)					
	{					
		Clear(pNode->pLeft);				
		Clear(pNode->pRight);				
		delete pNode;				
		pNode=NULL;				
	}					
}						
						
template<class T> 						
bool BSortTree<T>::IsEmpty()						
{						
	return size==0 ? true : false;					
}						
						
template<class T> 						
TreeNode<T>* BSortTree<T>::Search(T element)						
{						
	return SearchNode(m_pRoot, element);					
}						
template<class T> 						
TreeNode<T>* BSortTree<T>::SearchNode(TreeNode<T>* pNode,T element)						
{						
	if(pNode == NULL)					//如果節點為NULL
	{					
		return NULL;				
	}					
	else if(element == pNode->element)					//如果相等
	{					
		return pNode;				
	}					
	else if(element < pNode->element)		//如果比節點的元素小 向左找			
	{					
		return SearchNode(pNode->pLeft,element);				
	}					
	else					//如果比節點的元素大 向右找
	{					
		return SearchNode(pNode->pRight,element);				
	}					
}						
						
template<class T> 						
void BSortTree<T>::Delete(T element)						
{						
	if (! m_pRoot == NULL)	//指標為空則二叉樹沒有成員
	{
		printf("No member is in the binary tree and cannot be deleted!\n");
	}
	else  //呼叫DeleteNode()方法刪除節點
	{
		TreeNode<T>* ptemp = SearchNode(m_pRoot , element);
		DeleteNode(element, ptemp);
	}
	
}						
						
template<class T> 						
TreeNode<T>* BSortTree<T>::DeleteNode(T element,TreeNode<T>* pNode)						
{						
						
	if (!pNode->pLeft && !pNode->pRight)	//無左子樹也無右子樹
	{
		if (pNode->element < pNode->pParent->element)
		{
			pNode->pParent->pLeft = NULL;
		}
		else
		{
			pNode->pParent->pRight = NULL;
		}
		delete pNode;
	}
	
	else if (pNode->pLeft && !pNode->pRight)	//有左子樹無右子樹
	{
		if (pNode->element < pNode->pParent->element)
		{
			pNode->pParent->pLeft = pNode->pLeft;
			pNode->pLeft->pParent = pNode->pParent;
		}
		else
		{
			pNode->pParent->pRight = pNode->pLeft;
			pNode->pLeft->pParent = pNode->pParent;
		}
		delete pNode;
	}

	else if (!pNode->pLeft && pNode->pRight)	//無左子樹有右子樹
	{
		if (pNode->elment < pNode->pParent->element)
		{
			pNode->pParent->pLeft = pNode->pRight;
			pNode->pRight->pParent = pNode->pParent;
		}
		else
		{
			pNode->pParent->pRight = pNode->p Right;
			pNode->pRight->pParent = pNode->pParent;
		}
		delete pNode;
	}
	else (pNode->pLeft && pNode->pRight)	//左右子樹都有
	{
		TreeNode<T>* pRightMinNode = GetRightMinNode(pNode->pRight);
		pNode->element = pRightMinNode->element;
		DeleteNode(pRightMinNode->element, pRightMinNode);
		
	}

	return NULL;					
}						
												
						
						
//測試程式碼:						
						
						
void TestInsert()						
{						
	//12 8 5 9 17 15 13					
	/*					
				12		
						
		8				17
						
	5		9		15	
						
				13		
						
	*/					
						
	BSortTree<int> tree;					
						
	tree.Insert(12);					
	tree.Insert(8);					
	tree.Insert(5);					
	tree.Insert(9);					
	tree.Insert(17);					
	tree.Insert(15);					
	tree.Insert(13);					
}						
						
void TestSearch()						
{						
	//12 8 5 9 17 15 13					
						
	BSortTree<int> tree;					
						
	tree.Insert(12);					
	tree.Insert(8);					
	tree.Insert(5);					
	tree.Insert(9);					
	tree.Insert(17);					
	tree.Insert(15);					
	tree.Insert(13);					
						
	TreeNode<int>* p = tree.Search(9);
	TreeNode<int>* q = tree.Search(17);			
						
	printf("The search value is:%d\nThe address of search value is:%x\n",p->element,p);	
	printf("The search value is:%d\nThe address of search value is:%x\n",q->element,q);				
}	


int main(int argc, char* argv[])
{
	TestInsert();
	TestSearch();

	return 0;
}