您的位置:首页 > 编程语言 > C语言/C++

C++实现二叉搜索树基本操作(递归+非递归+应用)

2017-04-02 12:16 447 查看
基本概念不再多讲,看下面的例子



有如图的序列,用插入法建立二叉搜索树并完成相关操作:

代码:

#pragma once

#include <iostream>
#include <assert.h>
#include <string>
using namespace std;

//结点定义
template <class K>
struct SearchBinaryTreeNode
{
K _key;
SearchBinaryTreeNode<K>* _left;
SearchBinaryTreeNode<K>* _right;

SearchBinaryTreeNode(const K& key)
:_key(key)
,_left(NULL)
,_right(NULL)
{}
};

//搜索二叉树
template <class  K>
class SearchBinaryTree
{
typedef SearchBinaryTreeNode<K> Node;
public:
SearchBinaryTree()
:_root(NULL)
{}

//中序遍历
void InOrder()
{
_InOrder(_root);
cout << endl;
}

//插入
bool Insert(const K& key)
{
//1.若为空树则建立一个结点给_root
if (NULL == _root)
{
_root = new Node(key);
return true;
}

//2.不为空,需要找到key的位置,parent记录上一个结点
//因为搜索二叉树的结点值唯一,所以可以唯一的确认待插入的节点位置
//cur为空时,cur即为该位置

Node* parent = _root;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}

else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
return false;
}

//找到位置以后判断链接关系,当父结点的值大,则链接在父节点左侧
if (key < parent->_key)
{
parent->_left = new Node(key);
return true;
}
//当父结点的值小,则链接在父节点右侧
else if (key > parent->_key)
{
parent->_right = new Node(key);
return true;
}
else return false;
}

bool InsertR(const K& key)
{
return _InsertR(_root, key);
}

//寻找
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_key > key)
{
cur = cur->_left;
}
else if (cur->_key < key)
{
cur = cur->_right;
}
else
return cur;
}
return NULL;
}

//递归法寻找
Node* FindR(const K& key)
{
return _FindR(_root, key);
}

//删除一个节点
bool Remove(const K& key)
{

//结点分为4类:叶子,左为空,右为空,左右均不为空
//其中叶子节点可划归为左为空或者右为空去处理

//找到该结点

Node* parent = NULL;
Node* cur = _root;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else
{
Node* del = cur;
//1.左为空

if (NULL == cur->_left)
{
if (NULL == parent)
{
_root = cur->_right;
}
else
{
if (parent->_left == cur)
parent->_left = cur->_right;
else
parent->_right = cur->_right;
}
}
//右为空
else if (NULL == cur->_right)
{
if (NULL == parent)
{
_root = cur->_left;
}
else
{
if (parent->_left == cur)
parent->_left = cur->_left;
else
parent->_right = cur->_left;
}

}
//左右均不为空,替换法删除
//用左子树的最右节点或者右子树的最左结点的值给待删结点
//然后删除左子树的最右节点或者右子树的最左结点
else
{
Node* subLeft = cur->_left;
Node* subparent = cur;
while (subLeft->_right)
{
subparent = subLeft;
subLeft = subLeft->_right;
}

cur->_key = subLeft->_key;
del = subLeft;

if (subparent->_right == subLeft)
subparent->_right = subLeft->_left;
else
subparent->_left = subLeft->_left;
}
delete del;
cur = NULL;
return true;
}
}
return false;
}

//递归法删除
bool RemoveR(const K& key)
{
return _RemoveR(_root, key);
}

protected:
bool _RemoveR(Node*& root, const K&key)
{

if (key < root->_key)
_RemoveR(root->_left,key);
else if (key > root->_key)
_RemoveR(root->_right, key);
else
{
Node* del = root;
if (root->_left == NULL)
root = root->_right;
else if (root->_right == NULL)
root = root->_left;
delete del;
return true;
}
return false;
}

Node* _FindR(Node* root, const K& key)
{
if (key == root->_key)
return root;
else if (key < root->_key)
return _FindR(root->_left, key);
else
return _FindR(root->_right, key);
}

bool _InsertR(Node*& root, const K& key)
{
if (NULL == root)
{
root = new Node(key);
return true;
}
else if (key > root->_key)
{
return _InsertR(root->_right, key);
}
else if (key < root->_key)
{
return _InsertR(root->_left, key);
}
else
return false;
}

void _InOrder(Node* root)
{
if (NULL == root)
{
return;
}
_InOrder(root->_left);
cout << root->_key << "  ";
_InOrder(root->_right);
}

protected:
Node* _root;
};

void Test()
{
int a[] = { 5,3,4,1,7,8,2,6,0,9 };
SearchBinaryTree<int> t;
for (size_t i = 0;i < sizeof(a) / sizeof(a[0]);++i)
{
t.Insert(a[i]);
}
t.Insert(12);
t.Insert(-1);
t.InOrder();
SearchBinaryTreeNode<int>* ret;
ret = t.Find(8);
cout << "t.Find(8): " << ret->_key << endl;

t.Remove(-1);t.InOrder();
t.Remove(0);t.InOrder();
t.Remove(1);t.InOrder();
t.Remove(2);t.InOrder();
t.Remove(3);t.InOrder();
t.Remove(4);t.InOrder();
t.Remove(6);t.InOrder();
t.Remove(7);t.InOrder();
t.Remove(8);t.InOrder();
t.Remove(9);t.InOrder();
t.Remove(12);t.InOrder();
t.Remove(5);t.InOrder();//这里执行之后元素全部删除,会输出一个空行

}

void TestR()
{
int a[] = { 5,3,4,1,7,8,2,6,0,9 };
SearchBinaryTree<int> t;
for (size_t i = 0;i < sizeof(a) / sizeof(a[0]);++i)
{
t.InsertR(a[i]);
}
t.InsertR(12);
t.InsertR(-1);
t.InOrder();
SearchBinaryTreeNode<int>* ret;
ret = t.FindR(8);
cout << "t.FindR(8): " << ret->_key << endl;

t.RemoveR(-1);t.InOrder();
t.RemoveR(0);t.InOrder();
t.RemoveR(1);t.InOrder();
t.RemoveR(2);t.InOrder();
t.RemoveR(3);t.InOrder();
t.RemoveR(4);t.InOrder();
t.RemoveR(5);t.InOrder();
t.RemoveR(6);t.InOrder();
t.RemoveR(7);t.InOrder();
t.RemoveR(8);t.InOrder();
t.RemoveR(9);t.InOrder();
t.RemoveR(12);t.InOrder();//输出空行
}

//搜索二叉树的应用:字典实现的基本原理
//key表示主键,value表示其附带信息(即所要查找的内容)
template <class K,class V>
struct BSTreeNode
{
K _key;
V _value;
BSTreeNode<K, V>* _left;
BSTreeNode<K, V>* _right;

BSTreeNode(const K& key = K(), const V& value = V())
:_key(key)
,_value(value)
,_left(NULL)
,_right(NULL)
{}

};

template <class K,class V>
class BSTree
{
typedef BSTreeNode<K, V>  Node;

public:
BSTree()
:_root(NULL)
{}

bool Insert(const K& key, const V& value)
{
return _Insert(_root, key, value);
}

const Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key < cur->_key)
cur = cur->_left;
else if (key > cur->_key)
cur = cur->_right;
else
return cur;
}
return false;

}
protected:
bool _Insert(Node*& root, const K& key, const V& value)
{
if (NULL == root)
{
root = new Node(key, value);
return true;
}
else if (key < root->_key)
{
return _Insert(root->_left, key, value);
}
else if (key > root->_key)
{
return _Insert(root->_right, key, value);
}
else return false;
}

protected:
Node* _root;
};

void TestKV()
{
BSTree<string, string> t;

t.Insert("string", "字符串");
t.Insert("some", "某些");
t.Insert("next", "下一个");

const BSTreeNode<string, string>* ret = t.Find("next");
cout << ret->_value << endl;//显然结果应该是:下一个
}


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: