二叉树经常会在笔试和面试中遇到,因此,有必要对二叉树的一些常见操作进行一下系统的学习。
二叉树的定义就不说了,数据结构里有,这里给出我自己写的一部分代码。
当然,代码还相当不完善。以后将代码改进成类的形式,并用上模板。
有位高手就写出了完善的代码:http://www.zhuxinquan.com/archives/2006/01/notes_of_introduction_to_algorithmbinary_search_tree.html
假设我们的二叉树如以下形式:
5
/ /
6 7
/ / / /
2 3 1 4
/
0
一般情况下,我们要对该二叉树进行的常操作有:
创建,各种形式的遍历,求深度,是否是平衡的二叉树,当然,还有插入,删除等。我这里只有前面的一些操作。待完善。。。
简单说明创建操作:我们通过输入一些整数来充当结点的值,当输入为-1时,该结点不会被创建
// 创建二叉树 输入顺序:5, 6, 2, 0, -1, -1, -1, 3, -1, -1, 7, 1, -1, -1, 4, -1, -1
// 5
// / /
// 6 7
// / / / /
// 2 3 1 4
// / /
// 0 (-1)
// / /
// (-1) (-1)
//
// 其中-1的结点实际上是没有被创建的,这里为了方便说明。(结点1和结点4没有画出-1的形式)
// 当左结点的值为-1时,停止创建该结点,返回上一层。准备进行其父结点的右子树的创建。
// 当右结点的值为-1时,停止创建该结点,返回上一层。其父结点的树的成功。
// 由于父结点已被创建成功,则开始进行爷爷结点的右子树的创建。
// 递归进行。
代码:
头文件:BTree.h
#include <tchar.h>
#include <assert.h>
#include <vector>
#include <map>
#include <list>
#include <stack>
#include <math.h>
#include <iostream>
using namespace std;
typedef struct _BTreeNode
{
int m_nData;
_BTreeNode* pLChild;
_BTreeNode* pRChild;
_BTreeNode()
{
m_nData = 0;
pLChild = NULL;
pRChild = NULL;
}
} BTREENODE_t, *LPBTREENODE;
// 通过从控制台输入数据来创建树
void CreateBTree(LPBTREENODE* ppRoot);
// 通过整数vector来创建树
void CreateBTree(LPBTREENODE* ppRoot, vector<int>& vecCreateData, int nCurrentIndex);
// 删除树
void DeleteBTree(LPBTREENODE lpRoot);
// 访问某个结点
void VisitNode(LPBTREENODE lpNode);
// 递归先序遍历
void PreOrderTraverse_Recursion(LPBTREENODE lpRoot);
// 非递归先序遍历
void PreOrderTraverse_NonRecursion(LPBTREENODE lpRoot);
// 递归中序遍历
void InOrderTraverse_Recursion(LPBTREENODE lpRoot);
// 非递归中序遍历
void InOrderTraverse_NonRecursion(LPBTREENODE lpRoot);
// 递归后序遍历
void PostOrderTraverse_Recursion(LPBTREENODE lpRoot);
// 非递归后序遍历
void PostOrderTraverse_NonRecursion(LPBTREENODE lpRoot);
// 非递按层遍历
void LayerTraverse(LPBTREENODE lpRoot);
// 二叉树的深度
int Depth(LPBTREENODE lpRoot);
// 是否是平衡二叉树
bool IsBalanceBTree(LPBTREENODE lpRoot);
CPP文件:BTree.cpp
#include "BTree.h"
void CreateBTree(LPBTREENODE* ppRoot)
{
int nData = 0;
cout << "请输入数字(-1表示该结点不被创建): ";
cin >> nData;
if (-1 == nData)
{
return;
}
LPBTREENODE lpNode = NULL;
lpNode = new BTREENODE_t;
lpNode->m_nData = nData;
*ppRoot = lpNode;
CreateBTree( &((*ppRoot)->pLChild) );
CreateBTree( &((*ppRoot)->pRChild) );
return;
}
void CreateBTree(LPBTREENODE* ppRoot, vector<int>& vecCreateData, int nCurrentIndex)
{
//assert( nCurrentIndex < vecCreateData.size() );
static int s_nCurIx = nCurrentIndex;
if ( nCurrentIndex >= vecCreateData.size() || -1 == vecCreateData.at(nCurrentIndex) )
{
s_nCurIx++;
return;
}
LPBTREENODE lpNode = NULL;
lpNode = new BTREENODE_t;
lpNode->m_nData = vecCreateData.at(nCurrentIndex);
*ppRoot = lpNode;
s_nCurIx++;
CreateBTree( &((*ppRoot)->pLChild), vecCreateData, s_nCurIx/*nCurrentIndex + 1*/ );
CreateBTree( &((*ppRoot)->pRChild), vecCreateData, s_nCurIx/*nCurrentIndex + 1*/ );
return;
}
void DeleteBTree(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return;
}
if (NULL == lpRoot->pLChild && NULL == lpRoot->pRChild)
{
delete lpRoot;
lpRoot = NULL;
return;
}
DeleteBTree(lpRoot->pLChild);
lpRoot->pLChild = NULL; // 子结点虽然被delete掉了,但是父结点还没将其指针设置为NULL
DeleteBTree(lpRoot->pRChild);
lpRoot->pRChild = NULL; // 子结点虽然被delete掉了,但是父结点还没将其指针设置为NULL
}
void VisitNode(LPBTREENODE lpNode)
{
if (lpNode != NULL)
{
cout << lpNode->m_nData << " ";
}
}
void PreOrderTraverse_Recursion(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return;
}
VisitNode(lpRoot);
PreOrderTraverse_Recursion(lpRoot->pLChild);
PreOrderTraverse_Recursion(lpRoot->pRChild);
}
void PreOrderTraverse_NonRecursion(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return;
}
stack<LPBTREENODE> tempStack;
LPBTREENODE lpNode = lpRoot;
while ( lpNode != NULL || !tempStack.empty() )
{
if (lpNode != NULL)
{
// 向左走,进栈,访问“根”结点,一直走到左子树的尽头
VisitNode(lpNode);
tempStack.push(lpNode);
lpNode = lpNode->pLChild;
}
else
{
// 退栈,准备遍历右子树(主要在于找到下一次循环遍历的“根”结点)
lpNode = tempStack.top();
tempStack.pop();
if (lpNode != NULL)
{
lpNode = lpNode->pRChild;
}
}
}
}
void InOrderTraverse_Recursion(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return;
}
InOrderTraverse_Recursion(lpRoot->pLChild);
VisitNode(lpRoot);
InOrderTraverse_Recursion(lpRoot->pRChild);
}
void InOrderTraverse_NonRecursion(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return;
}
stack<LPBTREENODE> tempStack;
LPBTREENODE lpNode = lpRoot;
while ( lpNode != NULL || !tempStack.empty() )
{
if (lpNode != NULL)
{
// 向左走,一直走到左子树的尽头
tempStack.push(lpNode);
lpNode = lpNode->pLChild;
}
else
{
// 访问结点,退栈,准备遍历右子树
lpNode = tempStack.top();
tempStack.pop();
if (lpNode != NULL)
{
VisitNode(lpNode);
lpNode = lpNode->pRChild;
}
}
}
}
void PostOrderTraverse_Recursion(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return;
}
PostOrderTraverse_Recursion(lpRoot->pLChild);
PostOrderTraverse_Recursion(lpRoot->pRChild);
VisitNode(lpRoot);
}
void PostOrderTraverse_NonRecursion(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return;
}
stack<LPBTREENODE> tempStack;
LPBTREENODE lpNode = lpRoot;
LPBTREENODE lpLastVisitNode = NULL;
while ( lpNode != NULL || !tempStack.empty() )
{
// 向左走,进栈,访问“根”结点,一直走到左子树的尽头
while (lpNode != NULL)
{
tempStack.push(lpNode);
lpNode = lpNode->pLChild;
}
lpNode = tempStack.top();
// 如果lpNode没有右孩子或者其右孩子已经被访问过
if (NULL == lpNode->pRChild || lpNode->pRChild == lpLastVisitNode)
{
VisitNode(lpNode);
tempStack.pop();
lpLastVisitNode = lpNode;
lpNode = NULL;
}
else
{
lpNode = lpNode->pRChild;
}
}
}
void LayerTraverse(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return;
}
vector<LPBTREENODE> vecParent;
vector<LPBTREENODE> vecChild;
int nSizeParent = 0;
int nSizeChild = 0;
vecParent.push_back(lpRoot);
while (vecParent.size() > 0)
{
nSizeParent = vecParent.size();
for (int nIx = 0; nIx < nSizeParent; ++nIx)
{
VisitNode( vecParent.at(nIx) );
if (vecParent.at(nIx)->pLChild != NULL)
{
vecChild.push_back(vecParent.at(nIx)->pLChild);
}
if (vecParent.at(nIx)->pRChild != NULL)
{
vecChild.push_back(vecParent.at(nIx)->pRChild);
}
}
vecParent.clear();
nSizeChild = vecChild.size();
for (int nIx = 0; nIx < nSizeChild; ++nIx)
{
vecParent.push_back(vecChild.at(nIx));
}
vecChild.clear();
}
}
int Depth(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return 0;
}
int nLDepth = Depth(lpRoot->pLChild);
int nRDepth = Depth(lpRoot->pRChild);
return 1 + (nLDepth > nRDepth ? nLDepth : nRDepth);
}
bool IsBalanceBTree(LPBTREENODE lpRoot)
{
if (NULL == lpRoot)
{
return true;
}
if (abs( Depth(lpRoot->pLChild) - Depth(lpRoot->pRChild) ) > 1)
{
return false;
}
return true;
}
测试程序:
#include "BTree.h"
void _tmain()
{
// 创建二叉树 输入顺序:5, 6, 2, 0, -1, -1, -1, 3, -1, -1, 7, 1, -1, -1, 4, -1, -1
// 5
// / /
// 6 7
// / / / /
// 2 3 1 4
// / /
// 0 (-1)
// / /
// (-1) (-1)
//
// 其中-1的结点实际上是没有被创建的,这里为了方便说明。
// 当左结点的值为-1时,停止创建该结点,返回上一层。准备进行其父结点的右子树的创建。
// 当右结点的值为-1时,停止创建该结点,返回上一层。其父结点的树的成功。
// 由于父结点已被创建成功,则开始进行爷爷结点的右子树的创建。
// 递归进行。
LPBTREENODE lpRoot = NULL;
//CreateBTree(&lpRoot); // 创建方式一
vector<int> vecData;
vecData.push_back(5);
vecData.push_back(6);
vecData.push_back(2);
vecData.push_back(0);
vecData.push_back(-1);
vecData.push_back(-1);
vecData.push_back(-1);
vecData.push_back(3);
vecData.push_back(-1);
vecData.push_back(-1);
vecData.push_back(7);
vecData.push_back(1);
vecData.push_back(-1);
vecData.push_back(-1);
vecData.push_back(4);
vecData.push_back(-1);
vecData.push_back(-1);
CreateBTree(&lpRoot, vecData, 0); // 创建方式二
cout << "递归先序遍历:/t/t";
PreOrderTraverse_Recursion(lpRoot);
cout << endl << "递归中序遍历:/t/t";
InOrderTraverse_Recursion(lpRoot);
cout << endl << "递归后序遍历:/t/t";
PostOrderTraverse_Recursion(lpRoot);
cout << endl;
cout << "非递归先序遍历:/t";
PreOrderTraverse_NonRecursion(lpRoot);
cout << endl << "非递归中序遍历:/t";
InOrderTraverse_NonRecursion(lpRoot);
cout << endl << "非递归后序遍历:/t";
PostOrderTraverse_Recursion(lpRoot);
cout << endl << "非递按层遍历:/t/t";
LayerTraverse(lpRoot);
cout << endl;
cout << "二叉树的深度:/t/t" << Depth(lpRoot) << endl;
cout << "是否是平衡二叉树:/t" << (IsBalanceBTree(lpRoot) ? "true" : "false") << endl;
DeleteBTree(lpRoot);
}