学习编程,数据结构是一大拦路虎。我到现在见到数据结构还是挺发怵的,能怎么办呢?多见几面就熟悉了呗。我在学习数据结构的过程中,使用的是清华大学出版社邓俊辉老师的书。之前也学习过殷人昆老师的书,殷老师的书比较适合新手吧,代码看起来比较清晰。反观邓老师的书一直在封装和继承,相对来说邓老师的书更符合C++的编程理念。但两本书都讲的非常好,邓老师的书还配有免费的在线公开课,配套食用更佳。大家可以随意选择。
本篇博客要说明的是一种比较简单的二叉树结构-二叉搜索树。
首先,来看一下二叉搜索树的基本概念:
若二叉树中的各个节点所对应的词条支持大小的比较,则不在致歧义的情况下,我们对二叉树中的节点、节点对应的词条、以及词条内部的关键码不做区分。所谓的二叉搜索树(binary search tree)中处处满足顺序性:任一节点r的左(右)子树中,所有的节点(若存在)均不大于(不小于)r。
为了回避边界的情况,这里不妨暂且假定所有节点互不相等。于是上述的顺序性就可以简述表示为:任一节点r的左(右)子树中,所有节点(若存在)均小于(大于)r。
当然在实际的应用中,我们应该要对相等做处理,上图中的第一个反例就会转化成合法的二叉搜索树。
下面实现BST树的一些基本的功能:
BST树的头文件:
#ifndef UNTITLED1_HEAD_H
#define UNTITLED1_HEAD_H
#include<iostream>
#include<stack>
#include<assert.h>
using namespace std;
template<class Type>
class BSTree;
template<class Type>
class BSTNode
{
friend class BSTree<Type>;
public:
BSTNode() : data(Type()), leftChild(NULL), rightChild(NULL)
{}
BSTNode(Type d, BSTNode<Type>*left=NULL, BSTNode<Type>*right=NULL)
:data(d), leftChild(left), rightChild(right)
{}
~BSTNode()
{}
public:
Type GetData()const
{return data;}
BSTNode<Type>* GetLeftChild()const
{return leftChild;}
BSTNode<Type>* GetRightChild()const
{return rightChild;}
public:
void SetData(Type d)
{data = d;}
void SetLeftChild(BSTNode<Type> *left)
{leftChild = left;}
void SetRightChild(BSTNode<Type> *right)
{rightChild = right;}
private:
Type data;
BSTNode<Type> *leftChild;
BSTNode<Type> *rightChild;
};
template<class Type>
class BSTree
{
public:
BSTree() : root(NULL)
{}
public:
Type Min()const
{
assert(root != NULL);
return Min(root);
}
Type Max()const
{
assert(root != NULL);
return Max(root);
}
void Sort()const
{
Sort(root);
}
bool Remove(const Type &key)
{
return Remove(root, key);
}
public:
Type Min(BSTNode<Type> *t)const
{
while(t->leftChild != NULL)
t = t->leftChild;
return t->data;
}
Type Max(BSTNode<Type> *t)const
{
while(t->rightChild != NULL)
t = t->rightChild;
return t->data;
}
void Sort(BSTNode<Type> *t)const
{
if(t != NULL)
{
Sort(t->leftChild);
cout<<t->data<<" ";
Sort(t->rightChild);
}
}
bool Insert(const Type &x)
{
return Insert(root, x);
}
bool Remove(BSTNode<Type> *&t, const Type &key)
{
if(t == NULL)
return false;
if(key < t->data)
Remove(t->leftChild, key);
else if(key > t->data)
Remove(t->rightChild, key);
else
{
if(t->leftChild==NULL && t->rightChild==NULL)
{
delete t;
t = NULL;
}
else if(t->leftChild!=NULL && t->rightChild==NULL)
{
BSTNode<Type> *q = t;
t = t->leftChild;
delete q;
}
else if(t->leftChild==NULL && t->rightChild!=NULL)
{
BSTNode<Type> *q = t;
t = t->rightChild;
delete q;
}
else
{
BSTNode<Type> *p = t->rightChild;
while(p->leftChild != NULL)
p = p->leftChild;
t->data = p->data;
Remove(t->rightChild, p->data);
}
}
return true;
}
/*
bool Remove(BSTNode<Type> *&t, const Type &key)
{
if(t == NULL)
return false;
if(key < t->data)
Remove(t->leftChild, key);
else if(key > t->data)
Remove(t->rightChild, key);
else
{
BSTNode<Type> *p;
if(t->leftChild!=NULL && t->rightChild!=NULL)
{
p = t->rightChild;
while(p->leftChild != NULL)
p = p->leftChild;
t->data = p->data;
Remove(t->rightChild, p->data);
}
else
{
p = t;
if(p->leftChild != NULL)
t = t->leftChild;
else
t = t->rightChild;
delete p;
p = NULL;
}
}
return true;
}
*/
protected:
bool Insert(BSTNode<Type> *&t, const Type &x)
{
if(t == NULL)
{
t = new BSTNode<Type>(x);
if(t == NULL)
return false;
}
else if(x < t->data)
Insert(t->leftChild, x);
else if(x > t->data)
Insert(t->rightChild, x);
else
return false;
return true;
}
private:
BSTNode<Type> *root;
};
#endif //UNTITLED1_HEAD_H
main.cpp:
#include "head.h"
int main()
{
int ar[] = {16,3,7,11,9,26,18,14,15};
//int ar[] = {53,78,65,17,87,9,81,45,23};
//int ar[] = {53,78,65,17,87,9,89,45,23};
int n = sizeof(ar) / sizeof(int);
BSTree<int> bst;
for(int i=0; i<n; ++i)
{
bst.Insert(ar[i]);
}
//bst.Remove(53);
//cout<<"Min value = "<<bst.Min()<<endl;
//bst.Sort();
return 0;
}
下图是要插入的二叉搜索树的样子:
debug程序后,观察变量,符合预期要插入的的二叉搜素树的结构:
二叉搜索树的方法可能还不是很全,后续会继续补充。二叉搜索树是后面学习AVL树和红黑树的基础,所以一定要重视。
PS:在说明二叉搜索树的时候,引用了邓俊辉老师《数据结构》一书中的两张图,特此说明。