二叉樹的實現
/*********************************************************
* Description:參數傳遞:C++ 二叉樹的實現以及指針使用注意事項
* Author:charley
* DateTime:2010-12-8 11:00
* Compile Environment:win7+vs2008
***********************************************************/
#include <iostream>
using namespace std;
//*************************************************************************************
//二叉樹結點類的定義
template<class T> //模版結構體
struct TreeNode
{
T data; //節點的內容
TreeNode <T> *Lchild,*Rchild; //節點的左子樹和右子樹
//可選擇參數的默認構造函數
/*TreeNode(T nodeValue = T(),TreeNode<T> *leftNode = NULL,TreeNode<T> *rightNode = NULL )
:data(nodeValue),Lchild(leftNode),Rchild(rightNode){} */
};
//**************************************************************************************
//二叉樹的建立
template <class T> //模版方法
void createBinaryTree(TreeNode<T> *&root ) //傳遞指針的引用
{
TreeNode<T>* p = root;
T nodeValue ;
cin>>nodeValue;
if(nodeValue==-1)
{
root=NULL;
}
else
{
root=new TreeNode<T>(); //構造一個節點
root->data = nodeValue;
createBinaryTree(root->Lchild); //遞歸構造左子樹
createBinaryTree(root->Rchild); //遞歸構造右子樹
}
}
//************************************************************************************
//二叉樹的先序遍歷
template <class T>
void preOrder( TreeNode<T> * & p) //傳遞指針的引用
{
if(p)
{
cout<<p->data<<" ";
preOrder(p->Lchild);
preOrder(p->Rchild);
}
}
//**************************************************************************************
//二叉樹的中序遍歷
template <class T>
void inOrder(TreeNode<T> * & p) //傳遞指針的引用
{
if(p)
{
inOrder(p->Lchild);
cout<<p->data<<" ";
inOrder(p->Rchild);
}
}
//**************************************************************************************
//二叉樹的後序遍歷
template <class T>
void postOrder(TreeNode<T> *& p) //傳遞指針的引用
{
if(p)
{
postOrder(p->Lchild);
postOrder(p->Rchild);
cout<<p->data<<" ";
}
}
//*************************************************************************************
//統計二叉樹中結點的個數
template<class T>
int countNode(TreeNode<T> * & p) //傳遞指針的引用
{
if(p == NULL) return 0;
return 1+countNode(p->Lchild)+countNode(p->Rchild);
}
//***********************************************************************************
//求二叉樹的深度
template<class T>
int depth(TreeNode<T> *& p) //傳遞指針的引用
{
if(p == NULL)
return -1;
int h1 = depth(p->Lchild);
int h2 = depth(p->Rchild);
if(h1>h2)return (h1+1);
return h2+1;
}
//***********************************************************************************
//二叉樹的消毀操作
//容易混淆的錯誤聲明:void destroy(TreeNode<T>* p) 這種聲明會創建一個局部的臨時對象來保存傳遞的指針
//雖然2個指針都執行同一塊堆空間,delete局部指針 也會刪除二叉樹結構所佔用的堆內存
//但是全局傳遞的那個指針將會是垃圾指針,會產生不可預料的錯誤
//void destroy(TreeNode<T> *& p) 此函數的參數爲全局指針的一個別名,代表全局指針rootNode本身
// 這樣p = NULL;能達到置空指針的左右
//可選的方案是在調用完destroy方法之後,在主函數中執行rootNode = NULL操作
template<class T>
void destroy(TreeNode<T> *& p) //傳遞指針的引用,消毀函數,用來消毀二叉樹中的各個結點
{
if(p)
{
//錯誤 return之後 沒有執行delete p
//return destroy(p->Lchild);
//return destroy(p->Rchild);
destroy(p->Lchild);
destroy(p->Rchild);
//delete只能釋放由用戶通過new方式在堆中申請的內存,
//是通過變量聲明的方式由系統所聲明的棧內存不能使用delete刪除
//delete和free函數一樣,不修改它參數對應指針指向的內容,也不修改指針本身,
//只是在堆內存管理結構中將指針指向的內容標記爲可被重新分配
delete p;
//堆上內存釋放 棧上指針並不銷燬
//此時p指向的地址未知,此時執行*p = ? 操作會導致不可預料的錯誤
//但是可以重新賦值p = &x;
//最好delete之後把P置空
p = NULL;
}
}
//********************************************************************************
//主函數的設計
int main ()
{
TreeNode<int> * rootNode = NULL;
int choiced = 0;
while(true)
{
system("cls"); //清屏
cout<<"\n\n\n ---主界面---\n\n\n";
cout<<" 1、創建二叉樹 2、先序遍歷二叉樹\n";
cout<<" 3、中序遍歷二叉樹 4、後序遍歷二叉樹\n";
cout<<" 5、統計結點總數 6、查看樹深度 \n";
cout<<" 7、消毀二叉樹 0、退出\n\n";
cout<<" 請選擇操作:";
cin>>choiced;
if(choiced == 0)
return 0;
else if(choiced == 1)
{
system("cls");
cout<<"請輸入每個結點,回車確認,並以-1結束:\n";
createBinaryTree(rootNode );
}
else if(choiced == 2)
{
system("cls");
cout<<"先序遍歷二叉樹結果:\n";
preOrder(rootNode);
cout<<endl;
system("pause"); //暫停屏幕
}
else if(choiced == 3)
{
system("cls");
cout<<"中序遍歷二叉樹結果:\n";
inOrder(rootNode);
cout<<endl;
system("pause");
}
else if(choiced == 4)
{
system("cls");
cout<<"後序遍歷二叉樹結果:\n";
postOrder(rootNode);
cout<<endl;
system("pause");
}
else if(choiced == 5)
{
system("cls");
int count = countNode(rootNode);
cout<<"二叉樹中結點總數爲"<<count<<endl;
system("pause");
}
else if(choiced == 6)
{
system("cls");
int dep = depth(rootNode);
cout<<"此二叉樹的深度爲"<<dep<<endl;
system("pause");
}
else if(choiced == 7)
{
system("cls");
cout<<"二叉樹已被消毀!\n";
destroy(rootNode);
cout<<endl;
system("pause");
}
else
{
system("cls");
cout<<"\n\n\n\n\n\t錯誤選擇!\n";
}
}
}
* Description:參數傳遞:C++ 二叉樹的實現以及指針使用注意事項
* Author:charley
* DateTime:2010-12-8 11:00
* Compile Environment:win7+vs2008
***********************************************************/
#include <iostream>
using namespace std;
//*************************************************************************************
//二叉樹結點類的定義
template<class T> //模版結構體
struct TreeNode
{
T data; //節點的內容
TreeNode <T> *Lchild,*Rchild; //節點的左子樹和右子樹
//可選擇參數的默認構造函數
/*TreeNode(T nodeValue = T(),TreeNode<T> *leftNode = NULL,TreeNode<T> *rightNode = NULL )
:data(nodeValue),Lchild(leftNode),Rchild(rightNode){} */
};
//**************************************************************************************
//二叉樹的建立
template <class T> //模版方法
void createBinaryTree(TreeNode<T> *&root ) //傳遞指針的引用
{
TreeNode<T>* p = root;
T nodeValue ;
cin>>nodeValue;
if(nodeValue==-1)
{
root=NULL;
}
else
{
root=new TreeNode<T>(); //構造一個節點
root->data = nodeValue;
createBinaryTree(root->Lchild); //遞歸構造左子樹
createBinaryTree(root->Rchild); //遞歸構造右子樹
}
}
//************************************************************************************
//二叉樹的先序遍歷
template <class T>
void preOrder( TreeNode<T> * & p) //傳遞指針的引用
{
if(p)
{
cout<<p->data<<" ";
preOrder(p->Lchild);
preOrder(p->Rchild);
}
}
//**************************************************************************************
//二叉樹的中序遍歷
template <class T>
void inOrder(TreeNode<T> * & p) //傳遞指針的引用
{
if(p)
{
inOrder(p->Lchild);
cout<<p->data<<" ";
inOrder(p->Rchild);
}
}
//**************************************************************************************
//二叉樹的後序遍歷
template <class T>
void postOrder(TreeNode<T> *& p) //傳遞指針的引用
{
if(p)
{
postOrder(p->Lchild);
postOrder(p->Rchild);
cout<<p->data<<" ";
}
}
//*************************************************************************************
//統計二叉樹中結點的個數
template<class T>
int countNode(TreeNode<T> * & p) //傳遞指針的引用
{
if(p == NULL) return 0;
return 1+countNode(p->Lchild)+countNode(p->Rchild);
}
//***********************************************************************************
//求二叉樹的深度
template<class T>
int depth(TreeNode<T> *& p) //傳遞指針的引用
{
if(p == NULL)
return -1;
int h1 = depth(p->Lchild);
int h2 = depth(p->Rchild);
if(h1>h2)return (h1+1);
return h2+1;
}
//***********************************************************************************
//二叉樹的消毀操作
//容易混淆的錯誤聲明:void destroy(TreeNode<T>* p) 這種聲明會創建一個局部的臨時對象來保存傳遞的指針
//雖然2個指針都執行同一塊堆空間,delete局部指針 也會刪除二叉樹結構所佔用的堆內存
//但是全局傳遞的那個指針將會是垃圾指針,會產生不可預料的錯誤
//void destroy(TreeNode<T> *& p) 此函數的參數爲全局指針的一個別名,代表全局指針rootNode本身
// 這樣p = NULL;能達到置空指針的左右
//可選的方案是在調用完destroy方法之後,在主函數中執行rootNode = NULL操作
template<class T>
void destroy(TreeNode<T> *& p) //傳遞指針的引用,消毀函數,用來消毀二叉樹中的各個結點
{
if(p)
{
//錯誤 return之後 沒有執行delete p
//return destroy(p->Lchild);
//return destroy(p->Rchild);
destroy(p->Lchild);
destroy(p->Rchild);
//delete只能釋放由用戶通過new方式在堆中申請的內存,
//是通過變量聲明的方式由系統所聲明的棧內存不能使用delete刪除
//delete和free函數一樣,不修改它參數對應指針指向的內容,也不修改指針本身,
//只是在堆內存管理結構中將指針指向的內容標記爲可被重新分配
delete p;
//堆上內存釋放 棧上指針並不銷燬
//此時p指向的地址未知,此時執行*p = ? 操作會導致不可預料的錯誤
//但是可以重新賦值p = &x;
//最好delete之後把P置空
p = NULL;
}
}
//********************************************************************************
//主函數的設計
int main ()
{
TreeNode<int> * rootNode = NULL;
int choiced = 0;
while(true)
{
system("cls"); //清屏
cout<<"\n\n\n ---主界面---\n\n\n";
cout<<" 1、創建二叉樹 2、先序遍歷二叉樹\n";
cout<<" 3、中序遍歷二叉樹 4、後序遍歷二叉樹\n";
cout<<" 5、統計結點總數 6、查看樹深度 \n";
cout<<" 7、消毀二叉樹 0、退出\n\n";
cout<<" 請選擇操作:";
cin>>choiced;
if(choiced == 0)
return 0;
else if(choiced == 1)
{
system("cls");
cout<<"請輸入每個結點,回車確認,並以-1結束:\n";
createBinaryTree(rootNode );
}
else if(choiced == 2)
{
system("cls");
cout<<"先序遍歷二叉樹結果:\n";
preOrder(rootNode);
cout<<endl;
system("pause"); //暫停屏幕
}
else if(choiced == 3)
{
system("cls");
cout<<"中序遍歷二叉樹結果:\n";
inOrder(rootNode);
cout<<endl;
system("pause");
}
else if(choiced == 4)
{
system("cls");
cout<<"後序遍歷二叉樹結果:\n";
postOrder(rootNode);
cout<<endl;
system("pause");
}
else if(choiced == 5)
{
system("cls");
int count = countNode(rootNode);
cout<<"二叉樹中結點總數爲"<<count<<endl;
system("pause");
}
else if(choiced == 6)
{
system("cls");
int dep = depth(rootNode);
cout<<"此二叉樹的深度爲"<<dep<<endl;
system("pause");
}
else if(choiced == 7)
{
system("cls");
cout<<"二叉樹已被消毀!\n";
destroy(rootNode);
cout<<endl;
system("pause");
}
else
{
system("cls");
cout<<"\n\n\n\n\n\t錯誤選擇!\n";
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.