詳細二叉樹實現c++
前言
當初學資料結構遺留下來的程式碼。不過程式碼中空指標建議用nullptr, 而不要用0。當初沒有優化。
程式碼
#include <iostream>
#include<stack>
#include<queue>
using namespace std;
//二叉樹結點
template<class T>
struct BinTreeNode
{
T data;
BinTreeNode* leftchild, * rightchild;
BinTreeNode() : leftchild(0), rightchild(0) {}
BinTreeNode(T x, BinTreeNode* l = 0, BinTreeNode * r = 0) : data(x), leftchild(l), rightchild(r) {}
};
//後序非遞迴遍歷用到的結構
template<class T>
struct stkNode {
BinTreeNode<T>* ptr;
int tag; //0代表左,1代表右
stkNode(BinTreeNode<T>* N = 0) : ptr(N), tag(0) {}
};
template<class T>
class BinaryTree {
public:
BinaryTree() : root(0) {}
~BinaryTree() {}
//建樹
void Create();
void Create(BinTreeNode<T>*& BT, T endValue);
//刪除樹
void destroy();
void destroy(BinTreeNode<T>* subTree);
//前序,中序,後序遞迴遍歷演算法
void PreOrder(void(*visti)(BinTreeNode<T>* p)) const;
void InOrder(void(*visit)(BinTreeNode<T>* p)) const;
void PostOrder(void (*visit)(BinTreeNode<T>* p)) const;
//過載前序,中序,後序遞迴排序演算法
void PreOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p)) const;
void InOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p)) const;
void PostOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p)) const;
//前序,中序,後序非遞迴演算法
void PreOrderNonRecursion(void(*visit)(BinTreeNode<T>* p));
void InOrderNonRecursion(void(*visit)(BinTreeNode<T>* p));
void PostOrderNonRecursion(void(*visit)(BinTreeNode<T>* p));
//層次遍歷
void LevelOrder(void (*visit)(BinTreeNode<T>* p));
//求樹高
int Height() const;
int Height(BinTreeNode<T>* subTree) const;
int HeightNoRecursion();
//求節點個數
int Size() const; //從根開始
int Size(BinTreeNode<T>* subTree) const; //前序遍歷順序
int SizeNonRecursionByLevelOrder(); //非遞迴方法,層次遍歷順序
int SizeNonRecursionByPreOrder(); //非遞迴方法,前序遍歷順序
//求葉子結點總數
int LeavesSize() const; //從根開始
int LeavesSize(BinTreeNode<T>* t) const; //前序遍歷順序
int LeavesSizeNonRecursionByLevelOrder();
int LeavesSizeNonRecursionByPreOrder();
//廣義表輸出二叉樹
void PrintBinTree();
void PrintBinTree(BinTreeNode<T>* BT);
private:
BinTreeNode<T>* root;
};
//
//從根開始建立樹
template<class T>
void BinaryTree<T>::Create()
{
cout << "請輸入結束的標誌" << endl;
T endValue;
cin >> endValue;
cout << "請輸入二叉樹結點的值 (0結束)" << endl;
Create(root, endValue);
}
//前序順序建立二叉樹
template<class T>
void BinaryTree<T>::Create(BinTreeNode<T>*& BT, T endValue)
{
T x;
cin >> x;
if (x == endValue)
{
BT = 0;
}
else
{
BT = new BinTreeNode<T>(x);
Create(BT->leftchild, endValue);
Create(BT->rightchild, endValue);
}
}
//從根開始刪除
template<class T>
void BinaryTree<T>::destroy()
{
destroy(root);
}
//刪除以subtree為根的樹
template<class T>
void BinaryTree<T>::destroy(BinTreeNode<T>* subTree)
{
if (subTree != 0)
{
destroy(subTree->leftchild);
destroy(subTree->rightchild);
delete subTree;
}
root = 0; //不然刪完遍歷會報錯
}
//
//前序,中序,後序遞迴遍歷演算法
template<class T>
void BinaryTree<T>::PreOrder(void (*visit)(BinTreeNode<T>* p)) const
{
if (root == 0)
{
cout << "該樹為空" << endl;
return;
}
PreOrder(root, visit);
}
template<class T>
void BinaryTree<T>::InOrder(void (*visit)(BinTreeNode<T>* p)) const
{
if (root == 0)
{
cout << "該樹為空" << endl;
return;
}
InOrder(root, visit);
}
template<class T>
void BinaryTree<T>::PostOrder(void (*visit)(BinTreeNode<T>* p)) const
{
if (root == 0)
{
cout << "該樹為空" << endl;
return;
}
PostOrder(root, visit);
}
//前序,中序,後序遍歷過載
template<class T>
void BinaryTree<T>::PreOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p)) const
{
if (subTree != 0)
{
visit(subTree);
PreOrder(subTree->leftchild, visit);
PreOrder(subTree->rightchild, visit);
}
}
template<class T>
void BinaryTree<T>::InOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p)) const
{
if (subTree != 0)
{
InOrder(subTree->leftchild, visit);
visit(subTree);
InOrder(subTree->rightchild, visit);
}
}
template<class T>
void BinaryTree<T>::PostOrder(BinTreeNode<T>* subTree, void(*visit)(BinTreeNode<T>* p)) const
{
if (subTree != 0)
{
PostOrder(subTree->leftchild, visit);
PostOrder(subTree->rightchild, visit);
visit(subTree);
}
}
//非遞迴前序,中序,後序遍歷演算法
template<class T>
void BinaryTree<T>::PreOrderNonRecursion(void(*visit)(BinTreeNode<T>* p))
{
if (root == 0)
{
cout << "該樹為空" << endl;
return;
}
stack<BinTreeNode<T>*> S;
BinTreeNode<T>* p = root;
do
{
//一直往左,訪問並記錄結點以便返回
while (p != 0)
{
S.push(p);
visit(p);
p = p->leftchild;
}
if (!S.empty())
{
p = S.top();
S.pop();
p = p->rightchild;
}
} while (p != 0 || !S.empty());
cout << endl;
}
template<class T>
void BinaryTree<T>::InOrderNonRecursion(void(*visit)(BinTreeNode<T>* p))
{
if (root == 0)
{
cout << "該樹為空" << endl;
return;
}
stack<BinTreeNode<T>*> S;
BinTreeNode<T>* p = root;
do {
//一直往左,訪問並記錄結點以便返回
while (p != 0)
{
S.push(p);
p = p->leftchild;
}
if (!S.empty())
{
p = S.top();
S.pop();
visit(p);
p = p->rightchild;
}
} while (p != 0 || !S.empty());
cout << endl;
}
template<class T>
void BinaryTree<T>::PostOrderNonRecursion(void(*visit)(BinTreeNode<T>* p))
{
if (root == 0)
{
cout << "該樹為空" << endl;
return;
}
stack<stkNode<T>> S;
stkNode<T> w;
BinTreeNode<T>* p = root;
do
{
while (p != 0)
{
w.ptr = p;
w.tag = 0;
S.push(w);
p = p->leftchild;
}
bool continuing = true;
while (continuing && !S.empty())
{
w = S.top();
S.pop();
p = w.ptr;
switch (w.tag)
{
case 0:
w.tag = 1;
S.push(w);
continuing = false; //停止這個while迴圈,讓它去找最左的左子樹0
p = p->rightchild;
break;
case 1:
visit(p);
break;
}
}
} while (!S.empty());
cout << endl;
}
//層次遍歷
template<class T>
void BinaryTree<T>::LevelOrder(void(*visit)(BinTreeNode<T>* p))
{
queue<BinTreeNode<T>*> Q;
BinTreeNode<T>* p = root;
Q.push(p);//指向根節點的指標入隊
while (!Q.empty())
{
p = Q.front();
Q.pop();
visit(p);
if (p->leftchild != 0)
{
Q.push(p->leftchild);
}
if (p->rightchild != 0)
{
Q.push(p->rightchild);
}
}
}
//求樹高
template<class T>
int BinaryTree<T>::Height() const
{
return Height(root);
}
template<class T>
int BinaryTree<T>::Height(BinTreeNode<T>* subTree) const
{
if (subTree == 0)
{
return 0;
}
int leftchildHeight = Height(subTree->leftchild);
int rightchildHeight = Height(subTree->rightchild);
return (leftchildHeight > rightchildHeight) ? leftchildHeight + 1 : rightchildHeight + 1;
}
//非遞迴求樹高,層次遍歷順序
template<class T>
int BinaryTree<T>::HeightNoRecursion()
{
int depth = 0;
BinTreeNode<T>* p = root;
queue<BinTreeNode<T>*> q;
q.push(p); //根指標入隊
while (!q.empty())
{
depth++;
int width = q.size();
for (int i = 0; i < width; i++)
{
p = q.front();
q.pop();
if (p->leftchild != 0)
q.push(p->leftchild);
if (p->rightchild != 0)
q.push(p->rightchild);
}
}
return depth;
}
//求結點個數
template<class T>
int BinaryTree<T>::Size() const
{
return Size(root);
}
template<class T>
int BinaryTree<T>::Size(BinTreeNode<T>* subTree) const
{
if (subTree == 0)
return 0;
return 1 + Size(subTree->leftchild) + Size(subTree->rightchild);
}
//非遞迴求節點個數,層次遍歷順序
template<class T>
int BinaryTree<T>::SizeNonRecursionByLevelOrder()
{
//如果樹根為空,則節點數為0
if (root == 0)
return 0;
//如果不空,則可以執行下面的操作
int size = 1; //至少有根節點
BinTreeNode<T>* p = root;
queue<BinTreeNode<T>*> Q;
Q.push(p); 根指標入隊
while (!Q.empty())
{
int width = Q.size(); //獲取當前層次寬度,也就是知道下一層次的所有節點個數
for (int i = 0; i < width; i++)
{
p = Q.front(); //獲取隊頂元素
Q.pop(); //彈出隊頂元素
if (p->leftchild != 0)
{
size++;
Q.push(p->leftchild);
}
if (p->rightchild != 0)
{
size++;
Q.push(p->rightchild);
}
}
}
return size;
}
template<class T>
int BinaryTree<T>::SizeNonRecursionByPreOrder()
{
if (root == 0)
return 0;
stack<BinTreeNode<T>*> S;
BinTreeNode<T>* p = root;
int size = 0; //結點計數器
do
{
while (p != 0)
{
S.push(p);
size++;
p = p->leftchild;
}
if (!S.empty())
{
p = S.top();
S.pop();
p = p->rightchild;
}
} while (p != 0 || !S.empty());
return size;
}
//求葉子結點數目
template<class T>
int BinaryTree<T>::LeavesSize() const
{
return LeavesSize(root);
}
template<class T>
int BinaryTree<T>::LeavesSize(BinTreeNode<T>* t) const
{
if (t == 0)
return 0;
if (t->leftchild == 0 && t->rightchild == 0)
return 1;
return LeavesSize(t->leftchild) + LeavesSize(t->rightchild);
}
template<class T>
int BinaryTree<T>::LeavesSizeNonRecursionByLevelOrder()
{
//如果樹根為空,則節點數為0
if (root == 0)
return 0;
//初始時葉子結點計數器置0
int size = 0;
BinTreeNode<T>* p = root;
queue<BinTreeNode<T>*> Q;
Q.push(p); //根指標入隊
while (!Q.empty())
{
int width = Q.size(); //獲取當前層次寬度,也就是知道下一層次的所有節點個數
for (int i = 0; i < width; i++)
{
p = Q.front(); //獲取隊頂元素
Q.pop(); //彈出隊頂元素
if (p->leftchild == 0 && p->rightchild == 0)
{
size++;
}
else
{
if (p->leftchild != 0)
Q.push(p->leftchild);
if (p->rightchild != 0)
Q.push(p->rightchild);
}
}
}
return size;
}
template<class T>
int BinaryTree<T>::LeavesSizeNonRecursionByPreOrder()
{
if (root == 0)
return 0;
stack<BinTreeNode<T>*>S;
BinTreeNode<T>* p = root;
int size = 0;
do {
while (p != 0)
{
S.push(p);
//葉子結點呢
if (p->leftchild == 0 && p->rightchild == 0)
{
size++;
break;
}
p = p->leftchild;
}
if (!S.empty())
{
p = S.top();
S.pop();
p = p->rightchild;
}
} while (p != 0 || !S.empty());
return size;
}
//廣義表輸出二叉樹
template<class T>
void BinaryTree<T>::PrintBinTree()
{
PrintBinTree(root);
}
template<class T>
void BinaryTree<T>::PrintBinTree(BinTreeNode<T>* BT)
{
if (BT != 0)
{
cout << BT->data;
if (BT->leftchild != 0 || BT->rightchild != 0)
{
cout << "(";
PrintBinTree(BT->leftchild); // 遞迴輸出左子樹
if (BT->rightchild != 0)
{
cout << ",";
PrintBinTree(BT->rightchild); // 遞迴輸出右子樹
}
cout << ")";
}
}
}
//輸出結點data值的函式
template<class T>
void PrintData(BinTreeNode<T>* p)
{
cout << p->data << " ";
}
int main()
{
BinaryTree<char> a;
a.Create();
cout << endl << endl;
cout << "前序遞迴遍歷" << endl;
a.PreOrder(PrintData);
cout << endl << endl;
cout << "中序遞迴遍歷" << endl;
a.InOrder(PrintData);
cout << endl << endl;
cout << "後序遞迴遍歷" << endl;
a.PostOrder(PrintData);
cout << endl << endl << endl;
cout << "前序非遞迴遍歷" << endl;
a.PreOrderNonRecursion(PrintData);
cout << endl;
cout << "中序非遞迴遍歷" << endl;
a.InOrderNonRecursion(PrintData);
cout << endl;
cout << "後序非遞迴遍歷" << endl;
a.PostOrderNonRecursion(PrintData);
cout << endl;
cout << "層次遍歷" << endl;
a.LevelOrder(PrintData);
cout << endl;
cout << "遞迴求樹的高度" << endl;
cout << "height: " << a.Height();
cout << endl << endl;
cout << "非遞迴求樹的高度" << endl;
cout << "height: " << a.HeightNoRecursion();
cout << endl << endl << endl << endl;
cout << "遞迴求結點個數" << endl;
cout << "size: " << a.Size();
cout << endl << endl;
cout << "層次順序非遞迴求結點個數" << endl;
cout << "size: " << a.SizeNonRecursionByLevelOrder();
cout << endl << endl;
cout << "前序順序非遞迴求結點個數" << endl;
cout << "size: " << a.SizeNonRecursionByPreOrder();
cout << endl << endl;
cout << "***************************************************" << endl;
cout << endl << endl;
cout << "遞迴求葉子結點總數" << endl;
cout << "leavesSize: " << a.LeavesSize() << endl;
cout << endl << endl;
cout << "層次順序非遞迴方法求葉子結點總數" << endl;
cout << "leavesSize: " << a.LeavesSizeNonRecursionByLevelOrder() << endl;
cout << endl << endl;
cout << "前序順序非遞迴方法求葉子結點總數" << endl;
cout << "leavesSize: " << a.LeavesSizeNonRecursionByPreOrder() << endl;
cout << endl << endl;
cout << "廣義表輸出" << endl;
a.PrintBinTree();
cout << endl;
}
相關文章
- 深入理解二叉樹(超詳細)二叉樹
- 二叉樹實現二叉樹
- C++樹——遍歷二叉樹C++二叉樹
- C/C++ 二叉樹C++二叉樹
- js實現完全排序二叉樹、二叉搜尋樹JS排序二叉樹
- 霍夫曼樹(最優二叉樹)的實現二叉樹
- Java實現紅黑樹(平衡二叉樹)Java二叉樹
- JavaScript 二叉搜尋樹以及實現翻轉二叉樹JavaScript二叉樹
- 字典樹及其C++實現C++
- iOS實現反轉二叉樹iOS二叉樹
- 二叉樹的遍歷實現二叉樹
- java語言實現二叉樹Java二叉樹
- javascript實現二叉搜尋樹JavaScript
- python實現非平衡二叉樹Python二叉樹
- 平衡二叉樹(AVL樹)和 二叉排序樹轉化為平衡二叉樹 及C語言實現二叉樹排序C語言
- 最優二叉樹(哈夫曼樹)Java實現二叉樹Java
- 二叉搜尋樹的python實現Python
- 使用javascript實現排序二叉樹(2)JavaScript排序二叉樹
- 使用javascript實現排序二叉樹(1)JavaScript排序二叉樹
- 二叉查詢樹概念及實現
- java實現-資料結構之二叉樹(三):線索化二叉樹Java資料結構二叉樹
- 二叉樹實現按層 s型列印二叉樹
- Python實現二叉樹的增、刪、查Python二叉樹
- JavaScript實現簡單二叉查詢樹JavaScript
- 劍指offer——二叉樹的深度C++二叉樹C++
- 劍指offer——二叉樹的映象C++二叉樹C++
- 二叉樹詳解,包含程式碼二叉樹
- 用Python實現二叉樹的增、刪、查Python二叉樹
- 二叉樹的插入和搜尋–python實現二叉樹Python
- 24. 平衡二叉樹,及其程式碼實現二叉樹
- 小結:二叉樹的幾種實現方式二叉樹
- 如何在 Java 中實現二叉搜尋樹Java
- 第 34 題:如何實現二叉查詢樹?
- 二叉搜尋樹(Binary Search Tree)(Java實現)Java
- 滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹(二叉查詢樹)和最優二叉樹二叉樹
- 資料結構-二叉搜尋樹的實現資料結構
- 二叉樹的建立與遍歷(遞迴實現)二叉樹遞迴
- Java實現二叉搜尋樹的插入、刪除Java