github地址:https://github.com/lining91/BinTree
本文实现了二叉查找树的前序遍历(递归与非递归)、中序遍历(递归与非递归)、后序遍历(递归与非递归)、插入过程、删除过程、查找过程等。
二叉树的简单介绍:
1、二叉树中的每个节点都不能有多余两个的儿子。
2、二叉树的深度要比N小得多。
假设每个节点被指定一个关键字值(所有关键字是整数、互异的)。
二叉查找树的性质:
1、左子树的所有节点值均小于根节点值。
2、右子树的所有节点值均大于根节点值。
3、左右子树都满足上述两个条件。
插入过程:
1、若当前二叉树为空,则插入的元素为根节点。
2、若插入的元素值小于根节点值,则递归从根节点的左子树中找到可插入位置。
3、若插入的元素值大于根节点值,则递归从根节点的右子树中找到可插入位置。
删除过程:
1、待删除节点Z为叶子节点,则直接删除该节点。修改父节点的指针。
2、待删除节点Z为单支节点(只有左子树或者右子树),让Z的子树与Z的父节点相连,删除节点Z。
3、待删除节点Z左右子树都不为空。
方法一:找到Z的后继节点y,因为y一定没有左子树,所以可以直接删除y,并让y的父亲节点成为y的右子树的父亲节点。用y替换Z。
方法二:找到Z的前驱节点x,x一定没有右子树,所以可以直接删除x,并让x的父亲节点成为x的左子树的父亲节点。用x替换Z。
查找过程:
1、若待查找的元素值和根节点相同,则返回根节点。
2、若待查找的元素值小于根节点的元素值,则递归从根节点的左子树中查找。
3、若待查找的元素值大于根节点的元素值,则递归从根节点的右子树中查找。
遍历过程:
1、前序遍历(递归和非递归两种):先根节点,后左孩子节点,再右孩子结点。
2、中序遍历(递归和非递归两种):先左孩子结点,后根节点,再右孩子结点。
3、后序遍历(递归和非递归两种):先做孩子节点,后右孩子结点,再根节点。
获取最大元素的节点:
1、如果根节点无右子树,则返回根节点。
2、依次查询根节点的右子树节点,返回右子树的最后一个右节点。
获取最小元素的节点:
1、如果根节点无左子树,则返回根节点。
2、依次查询跟节点的左子树节点,返回左子树的最后一个左节点。
依次插入数据(15,3,20,8,10,18,6,1,26)之后的二叉树结构如下:
代码如下:
#include
#include
using namespace std;
typedef struct STreeNode* pSTreeNode;
typedef int TreeKeyType;
struct STreeNode
{
TreeKeyType key;
pSTreeNode pLeftChild;
pSTreeNode pRightChild;
STreeNode( TreeKeyType Value )
{
key = Value;
pLeftChild = NULL;
pRightChild = NULL;
}
};
class CBinTree
{
public:
CBinTree();
~CBinTree();
void Insert( TreeKeyType Value );
void Insert( pSTreeNode pNode, TreeKeyType Value );
pSTreeNode Search( TreeKeyType Value );
pSTreeNode Search( pSTreeNode pNode, TreeKeyType Value );
void Delete( TreeKeyType Value );
void Preorder( ); // 前序遍历,非递归方法(借用堆栈)
void Inorder( ); // 中序遍历,非递归方法(借用堆栈)
void Postorder( ); // 后序遍历,非递归方法(借用堆栈)
void PreorderRecursively( pSTreeNode pNode ); // 前序遍历,递归调用
void InorderRecursively( pSTreeNode pNode ); // 中序遍历,递归调用
void PostorderRecursively( pSTreeNode pNode ); // 后序遍历,递归调用
pSTreeNode GetMaxKey(); // 获得二叉查找树中元素值最大的节点
pSTreeNode GetMinKey(); // 获得二叉查找树中元素值最小的节点
void FreeMemory( pSTreeNode pNode ); // 释放内存
public:
pSTreeNode pRoot;
};
CBinTree::CBinTree()
{
pRoot = NULL;
}
CBinTree::~CBinTree()
{
if ( pRoot == NULL )
return;
FreeMemory( pRoot );
}
void CBinTree::FreeMemory( pSTreeNode pNode )
{
if ( pNode == NULL )
return;
if ( pNode->pLeftChild != NULL )
FreeMemory( pNode->pLeftChild );
if ( pNode->pRightChild != NULL )
FreeMemory( pNode->pRightChild );
delete pNode;
pNode = NULL;
}
void CBinTree::Insert( TreeKeyType Value )
{
if ( pRoot == NULL )
pRoot = new STreeNode( Value );
else
Insert( pRoot, Value );
}
void CBinTree::Insert( pSTreeNode pNode, TreeKeyType Value )
{
if ( pNode->key > Value )
{
if ( pNode->pLeftChild == NULL)
pNode->pLeftChild = new STreeNode( Value );
else
Insert( pNode->pLeftChild, Value );
}
else
{
if ( pNode->pRightChild == NULL)
pNode->pRightChild = new STreeNode( Value );
else
Insert( pNode->pRightChild, Value );
}
}
pSTreeNode CBinTree::Search( TreeKeyType Value )
{
return Search( pRoot, Value );
}
pSTreeNode CBinTree::Search( pSTreeNode pNode, TreeKeyType Value )
{
if ( pNode == NULL )
return NULL;
if ( pNode->key == Value )
return pNode;
else
{
if ( pNode->key > Value )
return Search( pNode->pLeftChild, Value );
else
return Search( pNode->pRightChild, Value );
}
}
void CBinTree::Delete( TreeKeyType Value )
{
pSTreeNode pParentNode = pRoot;
pSTreeNode pFindNode = pRoot;
// 找到Value元素对应的节点
while ( pFindNode != NULL )
{
if ( pFindNode->key == Value )
break;
pParentNode = pFindNode;
if ( pFindNode->key > Value )
pFindNode = pFindNode->pLeftChild;
else
pFindNode = pFindNode->pRightChild;
}
if ( pFindNode == NULL )
return;
// 处理Value元素的父节点和Value元素的节点
if ( pFindNode->pLeftChild == NULL || pFindNode->pRightChild == NULL )
{
// 一个子结点为空或者两个子结点都为空
pSTreeNode pTemp = NULL;
if ( pFindNode->pLeftChild != NULL)
pTemp = pFindNode->pLeftChild;
else if ( pFindNode->pRightChild != NULL )
pTemp = pFindNode->pRightChild;
if ( pParentNode->pLeftChild == pFindNode )
pParentNode->pLeftChild = pTemp;
else
pParentNode->pRightChild = pTemp;
delete pFindNode;
pFindNode = NULL;
}
else
{
// 找到前驱节点
pSTreeNode pTemp = pFindNode->pLeftChild;
pSTreeNode pTempParent = pFindNode;
while ( pTemp->pRightChild != NULL )
{
pTempParent = pTemp;
pTemp = pTemp->pRightChild;
}
pFindNode->key = pTemp->key;
pTempParent->pRightChild = NULL;
delete pTemp;
pTemp = NULL;
}
}
void CBinTree::Preorder( )
{
if ( pRoot == NULL )
{
cout << "二叉树为空!" << endl;
return;
}
stack StackTree;
pSTreeNode pNode = pRoot;
while( pNode != NULL || !StackTree.empty())
{
while ( pNode != NULL )
{
cout << " " << pNode->key << " ";
StackTree.push(pNode);
pNode = pNode->pLeftChild;
}
pNode = StackTree.top();
StackTree.pop();
pNode = pNode->pRightChild;
}
}
void CBinTree::Inorder( )
{
if ( pRoot == NULL )
{
cout << "二叉树为空!" << endl;
return;
}
stack StackTree;
pSTreeNode pNode = pRoot;
while ( pNode != NULL || !StackTree.empty() )
{
while ( pNode != NULL )
{
StackTree.push( pNode );
pNode = pNode->pLeftChild;
}
pNode = StackTree.top();
StackTree.pop();
cout << " " << pNode->key << " ";
pNode = pNode->pRightChild;
}
}
// 借助变量visited表示是否访问过该根节点。访问过的话,这输出。
void CBinTree::Postorder( )
{
if ( pRoot == NULL )
{
cout << "二叉树为空!" << endl;
return;
}
stack< pairbool >> StackTree;
StackTree.push( make_pair( pRoot, false ));
while ( !StackTree.empty() )
{
pSTreeNode pNode = StackTree.top().first;
bool bVisited = StackTree.top().second;
if (pNode == NULL)
{
StackTree.pop();
continue;
}
if (bVisited)
{
cout << " " << pNode->key << " ";
StackTree.pop();
}
else
{
StackTree.top().second = true;
StackTree.push( make_pair( pNode->pRightChild, false));
StackTree.push( make_pair( pNode->pLeftChild, false));
}
}
}
void CBinTree::PreorderRecursively( pSTreeNode pNode )
{
if (pNode == NULL)
return;
cout << " " << pNode->key << " ";
PreorderRecursively( pNode->pLeftChild );
PreorderRecursively( pNode->pRightChild );
}
void CBinTree::InorderRecursively( pSTreeNode pNode )
{
if (pNode == NULL)
return;
InorderRecursively( pNode->pLeftChild );
cout << " " << pNode->key << " ";
InorderRecursively( pNode->pRightChild );
}
void CBinTree::PostorderRecursively( pSTreeNode pNode )
{
if (pNode == NULL)
return;
PostorderRecursively( pNode->pLeftChild );
PostorderRecursively( pNode->pRightChild );
cout << " " << pNode->key << " ";
}
int main()
{
CBinTree* pBinTree = new CBinTree();
if ( pBinTree == NULL )
return 0;
pBinTree->Insert( 15 );
pBinTree->Insert( 3 );
pBinTree->Insert( 20 );
pBinTree->Insert( 8 );
pBinTree->Insert( 10 );
pBinTree->Insert( 18);
pBinTree->Insert( 6 );
pBinTree->Insert( 1);
pBinTree->Insert( 26);
pSTreeNode pRoot = pBinTree->pRoot;
cout << " 非递归前序遍历 :" ;
pBinTree->Preorder();
cout << endl;
cout << " 递归前序遍历 :" ;
pBinTree->PreorderRecursively( pRoot );
cout << endl;
cout << " 非递归中序遍历 :" ;
pBinTree->Inorder();
cout << endl;
cout << " 递归中序遍历 :" ;
pBinTree->InorderRecursively( pRoot );
cout << endl;
cout << " 非递归后序遍历 :" ;
pBinTree->Postorder();
cout << endl;
cout << " 递归后续遍历 :";
pBinTree->PostorderRecursively( pRoot );
cout << endl;
pSTreeNode pMaxNode = pBinTree->GetMaxKey();
pSTreeNode pMinNode = pBinTree->GetMinKey();
if ( pMaxNode != NULL )
cout << " 该二叉查找树的最大元素是:" << pMaxNode->key << endl;
if (pMinNode != NULL )
cout << " 该二叉查找树的最小元素是:" << pMinNode->key << endl;
TreeKeyType DeleteKey = 15;
pSTreeNode pSearchNode = pBinTree->Search( DeleteKey );
if ( pSearchNode != NULL )
cout << " 需要查询的元素是:" << DeleteKey << ", 实际查询到的元素是:" << pSearchNode->key << endl;
else
cout << " 没有查询到元素" << DeleteKey << endl;
pBinTree->Delete( DeleteKey );
cout << " 删除元素" << DeleteKey << "之后的递归前序遍历:";
pBinTree->PreorderRecursively( pRoot );
cout << endl;
DeleteKey = 1;
pBinTree->Delete( DeleteKey );
cout << " 删除元素" << DeleteKey << "之后的递归前序遍历:";
pBinTree->PreorderRecursively( pRoot );
cout << endl;
DeleteKey = 8;
pBinTree->Delete( DeleteKey );
cout << " 删除元素" << DeleteKey << "之后的递归前序遍历:";
pBinTree->PreorderRecursively( pRoot );
cout << endl;
DeleteKey = 26;
pBinTree->Delete( DeleteKey );
cout << " 删除元素" << DeleteKey << "之后的递归前序遍历:";
pBinTree->PreorderRecursively( pRoot );
cout << endl;
delete pBinTree;
pBinTree = NULL;
system( "pause" );
return 1;
}