您的位置:首页 > 理论基础 > 数据结构算法

数据结构——排序/搜索二叉树(非递归)的基本操作实现

2016-07-02 22:28 741 查看
什么是搜索二叉树:

二叉树(binary)是一种特殊的树。二叉树的每个节点最多只能有2个子节点:由于二叉树的子节点数目确定,所以可以直接采用上图方式在内存中实现。每个节点有一个左子节点(left children)和右子节点(right children)。左子节点是左子树的根节点,右子节点是右子树的根节点。

如果我们给二叉树加一个额外的条件,就可以得到一种被称作二叉搜索树(binary search tree)的特殊二叉树。二叉搜索树要求:每个节点都不比它左子树的任意元素小,而且不比它的右子树的任意元素大。

二叉搜索树可以方便的实现搜索算法。在搜索元素x的时候,我们可以将x和根节点比较:

1. 如果x等于根节点,那么找到x,停止搜索 (终止条件)

2. 如果x小于根节点,那么搜索左子树

3. 如果x大于根节点,那么搜索右子树

二叉搜索树所需要进行的操作次数最多与树的深度相等。n个节点的二叉搜索树的深度最多为n,最少为log(n)。

下面是用C++语言实现的二叉搜索树,并有搜索,插入,删除,寻找最大最小节点的操作。

"BSTree.h"

<strong><span style="font-size:18px;">#pragma once

template<class K,class V>
class BSTreeNode
{
public:
K _key;
V _value;

BSTreeNode<K,V>* _left;
BSTreeNode<K,V>* _right;

BSTreeNode(const K& key,const V& value)
:_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)
{
if (_root == NULL)
{
_root = new Node(key,value);
}

//_root != NULL
Node* cur = _root;
Node* parent = NULL;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else//cur->_key == key
{
return false;
}
}

if (parent->_key > key)
{
parent->_left = new Node(key,value);
}
else
{
parent->_right = new Node(key,value);
}
}

Node* Find(const K& key)
{
if (_root == NULL)
{
return NULL;
}

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;
}

bool ReMove(const K& key)
{
Node* cur = _root;
Node* parent = NULL;

while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else
{
break;
}
}

if (cur == NULL)//树不存在或者找不到的情况下
{
return false;
}

if (cur->_left == NULL)
{
//parent->_left = cur->_right;

if (parent == NULL)//处理删除节点为根节点的情况
{
_root = cur->_right;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
else //parent->_right == cur
{
parent->_right = cur->_right;
}
}
}
else if (cur->_right == NULL)
{
//parent->_right = cur->_left;
if (parent == NULL)//处理删除节点为根节点的情况
{
_root = cur->_left;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else //parent->_right == cur
{
parent->_right = cur->_left;
}
}
}
else//左右孩子都有节点
{
parent = cur;//这句代码刚刚忘记加了,导致程序崩溃
//要确保while循环进不去的时候,parent能有赋值
Node* tmp = cur->_right;
while (tmp->_left)
{
parent = tmp;
//找右孩子的最左节点
tmp = tmp->_left;
}

cur->_key = tmp->_key;
cur->_value = tmp->_value;

if (parent->_left == tmp)
{
parent->_left = tmp->_right;
}
else //parent->_right == tmp
{
parent->_right = tmp->_right;
}

delete tmp;//记得要释放内存
}
}

void InOrder()
{
return _InOrder(_root);
}
private:
void _InOrder(Node*& root)
{
if (root == NULL)
{
return;
}

_InOrder(root->_left);
cout<<root->_key<<" ";
_InOrder(root->_right);
}
private:
Node* _root;
};
</span></strong>


"test.cpp"

<strong><span style="font-size:18px;">#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include "BSTree.h"

void TestBSTree()
{
BSTree<int,int> bs;
int arr[] = {5,9,3,6,7,0,4,2,8,1};
int size = sizeof(arr)/sizeof(arr[0]);

for (int i = 0;i <size;i++)
{
bs.Insert(arr[i],i+1);
}

cout<<bs.Find(0)->_key<<endl;
cout<<bs.Find(0)->_value<<endl;

bs.InOrder();
cout<<endl;

bs.ReMove(0);
bs.ReMove(3);
bs.ReMove(4);
bs.ReMove(7);
bs.ReMove(8);
//bs.ReMove(55);

bs.InOrder();
cout<<endl;
}

int main()
{
TestBSTree();
system("pause");
return 0;
}</span></strong>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: