一、什么是二叉树
二叉树 (binary tree) 是另一种树型结构,它的特点是每个结点至多只有二棵子 树 (即二叉树中不存在度大于 2的结点 ),并且,二叉树的子树有左右之分,其次序不能任意颠倒 。 二叉树是一种数据结构 ,是一对多的关系。
二、二叉树的创建
第一步:想要构造一颗二叉树首先要创建二叉树的节点,然后将节点按照二叉树的规则连接起来就构成了一颗二叉树。二叉树的每个节点包含三个元素 ----->左指针域 pLeft ,右指针域 pRight ,数据域 data。
如图----->当有孩子时pLeft指向左孩子节点,pRight指向右孩子节点。
--------->当没有节点时指针指向空-->NULL
如何用代码创建节点:(创建一个模板类型的节点)
template<class T>
struct Node
{
Node()
{
LChild = NULL;
RChild = NULL;
}
Node(T d)
:data(d)
{
LChild = NULL;
RChild = NULL;
}
T data;
Node<T>* LChild;
Node<T>* RChild;
};template<class T>
struct Node
{
Node()
{
LChild = NULL;
RChild = NULL;
}
Node(T d)
:data(d)
{
LChild = NULL;
RChild = NULL;
}
T data;
Node<T>* LChild;
Node<T>* RChild;
};
开辟空间,将节点按照二叉树的规则连接
template<class T>
class BinTree
{
typedef Node<T>* PNode;
public:
BinTree() //无参构造
: _pRoot(NULL)
{}
BinTree(const T* array, size_t size, const T& invalid) //有参构造
{
size_t index = 0;
_CreateBinTree(_pRoot, array, size, index, invalid); //调用创建二叉树函数
}
BinTree(const BinTree& bt) //拷贝构造
{
_pRoot = _CopyBinTree(bt._pRoot); //调用拷贝函数
}
BinTree& operator=(const BinTree& bt) //赋值运算符重载
{
if (this == &bt)
return *this;
if (_pRoot != NULL)
_DestroyBinTree(_pRoot); //调用销毁函数
_pRoot = _CopyBinTree(bt._pRoot); //调用拷贝函数
return *this;
}
~BinTree() //析构函数
{
_DestroyBinTree(_pRoot); //调用销毁函数
}
}
将 创建函数,拷贝函数,销毁函数 定义成私有函数,只允许类的内部成员调用。
private:
// 根+左子树+右子树
void _CreateBinTree(PNode& pRoot, const T* array, size_t size, size_t& index, const T& invalid)
{
if (index >= size)
return;
if (index < size&&array[index]=='#')
return;
char ch = array[index];
pRoot = new Node<T>(ch);
_CreateBinTree(pRoot->LChild, array, size, ++index, invalid);
_CreateBinTree(pRoot->RChild, array, size, ++index, invalid);
}
PNode _CopyBinTree(PNode pRoot) //拷贝一个树
{
PNode newTree = NULL;
if (pRoot)
{
newTree = new Node<T>(pRoot->data);
if (pRoot->LChild)
newTree->LChild = _CopyBinTree(pRoot->LChild);
if (pRoot->RChild)
newTree->RChild = _CopyBinTree(pRoot->RChild);
}
return newTree;
}
void _DestroyBinTree(PNode& pRoot) //释放节点
{
if (pRoot == NULL)
return;
if (pRoot->LChild == NULL&&pRoot == NULL)
{
delete pRoot;
pRoot = NULL;
return;
}
_DestroyBinTree(pRoot->LChild);
_DestroyBinTree(pRoot->RChild);
delete pRoot;
pRoot = NULL;
}
到此一个二叉树的类就写好了,接下来写二叉树里的接口。
将要实现功能的函数都定义成私有函数,再写一个公有函数调用与其对应功能的私有函数,这样可以使对外接口使用起来更简单。
1.先序遍历
(1)递归实现
void _PreOrder(PNode pRoot) //先序遍历 根--->根的左子树---->根的右子树
{
if (pRoot != NULL)
{
cout << pRoot->data << " ";
_PreOrder(pRoot->LChild);
_PreOrder(pRoot->RChild);
}
}
(2)非递归
void _XPreOder(PNode pRoot)
{
if (pRoot == NULL)
return;
stack<PNode> s;
s.push(pRoot);
while (!s.empty())
{
PNode ret = s.top();
s.pop();
while (ret)
{
cout << ret->data << " ";
if (ret->RChild)
s.push(ret->RChild);
ret = ret->LChild;
}
}
}
2.中序遍历
(1)递归形式
void _InOrder(PNode pRoot) //中序遍历 左子树--->根节点--->右子树
{
if (pRoot != NULL)
{
_InOrder(pRoot->LChild);
cout << pRoot->data << " ";
_InOrder(pRoot->RChild);
}
}
(2)非递归形式
void _XInOder(PNode pRoot)
{
if (pRoot == NULL)
return;
stack<PNode> s;
PNode ret = pRoot;
while (ret || !s.empty())
{
while (ret)
{
s.push(ret);
ret = ret->LChild;
}
ret = s.top();
cout << ret->data << " ";
s.pop();
ret = ret->RChild;
}
}
3.后序遍历
(1)递归形式
void _PostOrder(PNode pRoot) //后序遍历 左子树--->右子树--->根节点
{
if (pRoot != NULL)
{
_PostOrder(pRoot->LChild);
_PostOrder(pRoot->RChild);
cout << pRoot->data<<" ";
}
}
(2)非递归形式
void _XPostOder(PNode pRoot)
{
if (pRoot == NULL)
return;
stack<PNode> s;
PNode ret = pRoot;
PNode flag = NULL;
while (ret || !s.empty())
{
while (ret)
{
s.push(ret);
ret = ret->LChild;
}
ret = s.top();
if (ret->RChild == NULL || flag == ret->RChild)
{
cout << ret->data << " ";
flag = ret;
s.pop();
ret = NULL;
}
else
ret =s.top()->RChild;
}
}
4.层序遍历
层序遍历就是一层一层访问
void _LevelOrder(PNode pRoot) //层序遍历
{
if (pRoot == NULL)
return;
PNode ret = NULL;
queue<PNode> q;
q.push(pRoot);
while (!q.empty())
{
ret = q.front();
cout << ret->data <<" ";
q.pop();
if (ret->LChild)
q.push(ret->LChild);
if (ret->RChild)
q.push(ret->RChild);
}
}
5.总节点个数
size_t _Size(PNode pRoot)
{
if (pRoot == NULL)
return 0;
if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
return 1;
return _Size(pRoot->LChild) + _Size(pRoot->RChild)+1;
}
6.叶子节点的总个数
size_t _GetLeefCount(PNode pRoot)
{
if (pRoot == NULL)
return 0;
if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
return 1;
return _GetLeefCount(pRoot->LChild) + _GetLeefCount(pRoot->RChild);
}
7.获取第k层节点的个数
size_t _GetKLevelCount(PNode pRoot,size_t k)
{
if (pRoot == NULL || k < 1)
return 0;
if (k == 1)
return 1;
return _GetKLevelCount(pRoot->LChild, k - 1) + _GetKLevelCount(pRoot->RChild, k - 1);
}
8.树的高度
size_t _Height(PNode pRoot)
{
if (pRoot == NULL)
return 0;
if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
return 1;
size_t Left = _Height(pRoot->LChild);
size_t Right = _Height(pRoot->RChild);
return (Left > Right ? Left + 1 : Right + 1);
}
9.查找某节点的位置
PNode _Find(PNode pRoot, const T& data)
{
if (pRoot == NULL)
return NULL;
if (pRoot->data == data)
return pRoot;
if (_Find(pRoot->LChild, data))
return _Find(pRoot->LChild,data);
if (_Find(pRoot->RChild, data))
return _Find(pRoot->RChild,data);
return NULL;
}
10.查找指定节点的双亲节点
PNode _Parent(PNode pRoot, PNode pNode)
{
if (pRoot == NULL)
return NULL;
if (pRoot->LChild == pNode || pRoot->RChild == pNode)
return pRoot;
if (_Parent(pRoot->LChild, pNode))
return _Parent(pRoot->LChild,pNode);
if (_Parent(pRoot->RChild, pNode))
return _Parent(pRoot->RChild, pNode);
return NULL;
}
11.查找指定节点的左孩子节点
PNode LeftChild(PNode pNode) //查找指定节点的左孩子节点
{
return pNode->LChild;
}
12.查找指定节点的右孩子节点
PNode RightChild(PNode pNode) //查找指定节点的右孩子节点
{
return pNode->RChild;
}
13.二叉树镜像
(1)递归实现
void _BinTreeMirror(PNode &pRoot) //递归实现
{
if (pRoot == NULL)
return;
swap(pRoot->LChild, pRoot->RChild);
_BinTreeMirror(pRoot->LChild);
_BinTreeMirror(pRoot->RChild);
}
(2)非递归实现
void _XBinTreeMirror(PNode &pRoot) //层序遍历实现
{
if (pRoot == NULL)
return;
queue<PNode> q;
q.push(pRoot);
PNode ret = NULL;
while (!q.empty())
{
ret = q.front();
q.pop();
swap(ret->LChild, ret->RChild);
if (ret->LChild)
q.push(ret->LChild);
if (ret->RChild)
q.push(ret->RChild);
}
}
14.判断是否是完全二叉树
首先,分析二叉树
(1)当二叉树为空时,是完全二叉树
(2)当二叉树只有一个节点时,是完全二叉树
(3)当二叉树有多个节点时---->
创建一个队,将根节点入队,然后进入循环;当对不为空,继续循环。
在循环外创建一个标记flag=false,在循环内使用;当false为true时,并且(ret->left!=NULL||ret->Right!=NULL)二叉树不是完全二叉树。
a.左右子树都存在,入队
b.只有左子树,没有右子树;不饱和点,将左子树入队,将标记flag=true;
c.只有右子树,没有左子树,不是完全二叉树
d.没有左子树,没有右子树;不饱和点,将标记flag=true
bool _IsComplateBinTree(PNode pRoot) //判断是否是完全二叉树
{
if (pRoot == NULL)
return true;
queue<PNode> q;
q.push(pRoot);
bool flag = false;
PNode ret = NULL;
while (!q.empty())
{
ret = q.front();
q.pop();
if (flag==true&&(ret->LChild||ret->RChild))
return false;
else
{
if (ret->LChild&&ret->RChild)
{
q.push(ret->LChild);
q.push(ret->RChild);
}
else if (ret->LChild&&ret->RChild == NULL)
{
q.push(ret->LChild);
flag = true;
}
else if (ret->LChild == NULL&&ret->RChild)
return false;
else
{
flag = true;
}
}
}
return true;
}
三、完整的二叉树代码
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
template<class T>
struct Node
{
Node()
{
LChild = NULL;
RChild = NULL;
}
Node(T d)
:data(d)
{
LChild = NULL;
RChild = NULL;
}
T data;
Node<T>* LChild;
Node<T>* RChild;
};
template<class T>
class BinTree
{
typedef Node<T>* PNode;
public:
BinTree()
: _pRoot(NULL)
{}
BinTree(const T* array, size_t size, const T& invalid)
{
size_t index = 0;
_CreateBinTree(_pRoot, array, size, index, invalid);
}
BinTree(const BinTree& bt)
{
_pRoot = _CopyBinTree(bt._pRoot);
}
BinTree& operator=(const BinTree& bt)
{
if (this == &bt)
return *this;
if (_pRoot != NULL)
_DestroyBinTree(_pRoot);
_pRoot = _CopyBinTree(bt._pRoot);
return *this;
}
~BinTree() //析构函数
{
_DestroyBinTree(_pRoot);
}
void PreOrder() //先序遍历
{
_PreOrder(_pRoot);
}
void InOrder() //中序遍历
{
_InOrder(_pRoot);
}
void PostOrder() //后序遍历
{
_PostOrder(_pRoot);
}
void LevelOrder() //层序遍历
{
_LevelOrder(_pRoot);
}
///
//非递归遍历
void XPreOder() //非递归前序遍历
{
_XPreOder(_pRoot);
}
void XInOder() //非递归中序遍历
{
_XInOder(_pRoot);
}
void XPostOder() //非递归后序遍历
{
_XPostOder(_pRoot);
}
///
//二叉树镜像
void BinTreeMirror() //递归实现
{
_BinTreeMirror(_pRoot);
}
void XBinTreeMirror() //层序遍历实现
{
_XBinTreeMirror(_pRoot);
}
///
size_t Size() //总结点个数
{
return _Size(_pRoot);
}
size_t GetLeefCount() //叶子节点的总个数
{
return _GetLeefCount(_pRoot);
}
size_t GetKLevelCount(size_t K) // 获取第K层结点的个数
{
return _GetKLevelCount(_pRoot, K);
}
size_t Height() //树的高度
{
return _Height(_pRoot);
}
PNode Find(const T& data) //查找某个节点的位置
{
return _Find(_pRoot, data);
}
PNode Parent(PNode pNode) //查找指定位置的双亲节点
{
return _Parent(_pRoot, pNode);
}
PNode LeftChild(PNode pNode) //查找指定节点的左孩子节点
{
return pNode->LChild;
}
PNode RightChild(PNode pNode) //查找指定节点的右孩子节点
{
return pNode->RChild;
}
bool IsComplateBinTree() //判断是否是完全二叉树
{
return _IsComplateBinTree(_pRoot);
}
private:
// 根+左子树+右子树
void _CreateBinTree(PNode& pRoot, const T* array, size_t size, size_t& index, const T& invalid)
{
if (index >= size)
return;
if (index < size&&array[index]=='#')
return;
char ch = array[index];
pRoot = new Node<T>(ch);
_CreateBinTree(pRoot->LChild, array, size, ++index, invalid);
_CreateBinTree(pRoot->RChild, array, size, ++index, invalid);
}
PNode _CopyBinTree(PNode pRoot) //拷贝一个树
{
PNode newTree = NULL;
if (pRoot)
{
newTree = new Node<T>(pRoot->data);
if (pRoot->LChild)
newTree->LChild = _CopyBinTree(pRoot->LChild);
if (pRoot->RChild)
newTree->RChild = _CopyBinTree(pRoot->RChild);
}
return newTree;
}
void _DestroyBinTree(PNode& pRoot) //释放节点
{
if (pRoot == NULL)
return;
if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
{
delete pRoot;
pRoot = NULL;
return;
}
_DestroyBinTree(pRoot->LChild);
_DestroyBinTree(pRoot->RChild);
delete pRoot;
pRoot = NULL;
}
void _PreOrder(PNode pRoot) //先序遍历 根--->根的左子树---->根的右子树
{
if (pRoot != NULL)
{
cout << pRoot->data << " ";
_PreOrder(pRoot->LChild);
_PreOrder(pRoot->RChild);
}
}
void _InOrder(PNode pRoot) //中序遍历 左子树--->根节点--->右子树
{
if (pRoot != NULL)
{
_InOrder(pRoot->LChild);
cout << pRoot->data << " ";
_InOrder(pRoot->RChild);
}
}
void _PostOrder(PNode pRoot) //后序遍历 左子树--->右子树--->根节点
{
if (pRoot != NULL)
{
_PostOrder(pRoot->LChild);
_PostOrder(pRoot->RChild);
cout << pRoot->data<<" ";
}
}
void _LevelOrder(PNode pRoot) //层序遍历
{
if (pRoot == NULL)
return;
PNode ret = NULL;
queue<PNode> q;
q.push(pRoot);
while (!q.empty())
{
ret = q.front();
cout << ret->data <<" ";
q.pop();
if (ret->LChild)
q.push(ret->LChild);
if (ret->RChild)
q.push(ret->RChild);
}
}
//
//非递归遍历函数定义
void _XPreOder(PNode pRoot)
{
if (pRoot == NULL)
return;
stack<PNode> s;
s.push(pRoot);
while (!s.empty())
{
PNode ret = s.top();
s.pop();
while (ret)
{
cout << ret->data << " ";
if (ret->RChild)
s.push(ret->RChild);
ret = ret->LChild;
}
}
}
void _XInOder(PNode pRoot)
{
if (pRoot == NULL)
return;
stack<PNode> s;
PNode ret = pRoot;
while (ret || !s.empty())
{
while (ret)
{
s.push(ret);
ret = ret->LChild;
}
ret = s.top();
cout << ret->data << " ";
s.pop();
ret = ret->RChild;
}
}
void _XPostOder(PNode pRoot)
{
if (pRoot == NULL)
return;
stack<PNode> s;
PNode ret = pRoot;
PNode flag = NULL;
while (ret || !s.empty())
{
while (ret)
{
s.push(ret);
ret = ret->LChild;
}
ret = s.top();
if (ret->RChild == NULL || flag == ret->RChild)
{
cout << ret->data << " ";
flag = ret;
s.pop();
ret = NULL;
}
else
ret =s.top()->RChild;
}
}
//
//二叉树镜像
void _BinTreeMirror(PNode &pRoot) //递归实现
{
if (pRoot == NULL)
return;
swap(pRoot->LChild, pRoot->RChild);
_BinTreeMirror(pRoot->LChild);
_BinTreeMirror(pRoot->RChild);
}
void _XBinTreeMirror(PNode &pRoot) //层序遍历实现
{
if (pRoot == NULL)
return;
queue<PNode> q;
q.push(pRoot);
PNode ret = NULL;
while (!q.empty())
{
ret = q.front();
q.pop();
swap(ret->LChild, ret->RChild);
if (ret->LChild)
q.push(ret->LChild);
if (ret->RChild)
q.push(ret->RChild);
}
}
//
size_t _GetKLevelCount(PNode pRoot,size_t k)
{
if (pRoot == NULL || k < 1)
return 0;
if (k == 1)
return 1;
return _GetKLevelCount(pRoot->LChild, k - 1) + _GetKLevelCount(pRoot->RChild, k - 1);
}
size_t _Size(PNode pRoot)
{
if (pRoot == NULL)
return 0;
if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
return 1;
return _Size(pRoot->LChild) + _Size(pRoot->RChild)+1;
}
size_t _GetLeefCount(PNode pRoot)
{
if (pRoot == NULL)
return 0;
if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
return 1;
return _GetLeefCount(pRoot->LChild) + _GetLeefCount(pRoot->RChild);
}
size_t _Height(PNode pRoot)
{
if (pRoot == NULL)
return 0;
if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
return 1;
size_t Left = _Height(pRoot->LChild);
size_t Right = _Height(pRoot->RChild);
return (Left > Right ? Left + 1 : Right + 1);
}
PNode _Find(PNode pRoot, const T& data)
{
if (pRoot == NULL)
return NULL;
if (pRoot->data == data)
return pRoot;
if (_Find(pRoot->LChild, data))
return _Find(pRoot->LChild,data);
if (_Find(pRoot->RChild, data))
return _Find(pRoot->RChild,data);
return NULL;
}
PNode _Parent(PNode pRoot, PNode pNode)
{
if (pRoot == NULL)
return NULL;
if (pRoot->LChild == pNode || pRoot->RChild == pNode)
return pRoot;
if (_Parent(pRoot->LChild, pNode))
return _Parent(pRoot->LChild,pNode);
if (_Parent(pRoot->RChild, pNode))
return _Parent(pRoot->RChild, pNode);
return NULL;
}
bool _IsComplateBinTree(PNode pRoot) //判断是否是完全二叉树
{
if (pRoot == NULL)
return true;
queue<PNode> q;
q.push(pRoot);
bool flag = false;
PNode ret = NULL;
while (!q.empty())
{
ret = q.front();
q.pop();
if (flag==true&&(ret->LChild||ret->RChild))
return false;
else
{
if (ret->LChild&&ret->RChild)
{
q.push(ret->LChild);
q.push(ret->RChild);
}
else if (ret->LChild&&ret->RChild == NULL)
{
q.push(ret->LChild);
flag = true;
}
else if (ret->LChild == NULL&&ret->RChild)
return false;
else
{
flag = true;
}
}
}
return true;
}
private:
PNode _pRoot;
};
void test1() ///从此开始下面的函数是测试函数
{
char *p = "ABC###DE##F";
BinTree<char> t1(p, strlen(p), '#');
/*t1.PreOrder();
cout << endl;
t1.InOrder();
cout << endl;
t1.PostOrder();
cout << endl;*/
//BinTree<char> t2(t1);
BinTree<char> t3;
t3 = t1;
}
void test2()
{
char *p = "ABC###DE##FG";
BinTree<char> t1(p, strlen(p), '#');
BinTree<char> t2;
cout << t1.Size() << endl;
cout << t1.GetLeefCount() << endl;
cout << t1.Height() << endl;
//char ret = 'F';
//if (t1.Find(ret)) //找节点
//{
// cout << t1.Find(ret)->data << endl;
//}
cout << t1.Parent(t1.Find('D'))->data << endl; //找双亲节点
cout << t1.GetKLevelCount(4) << endl;
t1.LevelOrder();
}
void test3()
{
char *p = "ABC###DE##F";
BinTree<char> t1(p, strlen(p), '#');
t1.PreOrder();
cout << endl;
t1.XPreOder();
cout << endl;
t1.InOrder();
cout << endl;
t1.XInOder();
cout << endl;
t1.PostOrder();
cout << endl;
t1.XPostOder();
}
void test4() //测试镜像
{
char *p = "ABC###DE##FG";
BinTree<char> t1(p, strlen(p), '#');
char *p2 = "ABC##D##EF###";
BinTree<char> t2(p2, strlen(p2), '#');
t1.PreOrder();
cout << endl;
t2.PreOrder();
cout << endl;
/*t1.BinTreeMirror();
t1.PreOrder();
cout << endl;
t1.XBinTreeMirror();
t1.PreOrder();*/
cout << t1.IsComplateBinTree() << endl;
cout << t2.IsComplateBinTree() << endl;
}
int main()
{
//test1();
//test2();
//test3();
test4();
system("pause");
return 0;
}