【编程珠玑】

看珠玑看了一半了,多是趁着闲着的时候看上几页,思考一下后面的问题。珠玑很薄,才两百来页,但是里面的一些技术却十分地实用,改天一定要好好整理一下,将写的程序和一些有趣的技术(编程思想,断言,数据表现形式)等话题展开探讨。很久没有写技术性的文字了,只是拿来简单的二叉查找树来练练手。

【二叉查找树】

二叉查找树是一种二叉树,由于其具有左子树的元素都小于根节点,右子树元素大于根节点的这种特性,故而使得查找起来的复杂度是O(lgN)。这种结构编码十分简单,而且效率很高,占用空间少,非常受欢迎。

首先定义一个节点数据结构,拥有一个value和左右孩子指针。

 

#include 
using namespace std;

class  Node
{
	public:
	int value;
	Node* leftChild;
	Node* rightChild;
	public:
		Node(int i) {value = i;leftChild = NULL;rightChild = NULL;}
};

 

下面就是一个递归的插入算法,十分地巧妙:

 

#include 
#include "Node.h"
#include 
#include 
using namespace std;


//二叉查找树
Node* insert(Node* p,int element);
void traverse(Node* p);
void search(int element,Node *p);
void main()
{
	//Node *root = new Node(0);
	//insert element into the tree
	srand(clock());
	Node *root = new Node(rand()%100);
	for(int i=1;i<20;i++)
	{
		insert(root,rand()%100);
	}
        traverse(root);
        int element ;
	cin >> element;
	search(element,root);
        system("pause");
}

Node* insert(Node* p,int element)
{
	if(p==NULL)
		p= new Node(element);
	else if(element < p->value)
	{
		p->leftChild = insert(p->leftChild,element);
	}
	else if(element >= p->value)
	{
		p->rightChild = insert(p->rightChild,element);
	}
	return p;
}

void traverse(Node* p) //中序遍历
{
	if(p == NULL)
		return;
	traverse(p->leftChild);
	cout << p->value << endl;
	traverse(p->rightChild);
	return;
}
其中插入算法的原理是如果该元素已经找到所在位置,即叶子处(条件p==NULL),否则如果小于根节点,说明要往左子树插入,递归调用insert函数。同理,如果大于或者等于根节点,则往右子树插入,递归调用insert函数。我们跟踪一次插入,假如有一棵树,如图所示,一开始是空的。

 

实现一个简单的BST_第1张图片

要插入元素5,由于p==NULL,故新建一个节点,插入。而要插入元素3,则满足条件二elementvalue,故而递归调用insert函数,往左子树插入,接着情况和在一颗空树中插入节点一样,插入节点后返回的是p的指针赋给5的左孩子。故而后面两步也很好理解了。递归的好处就在于,将情况都抽象出来了,编程会变得简单很多。

 

一颗树构造好之后,就要发挥它的目标功能了——>查找。使用递归定义的中序遍历,我们可以让整棵树从小道大的序列输出。当然我们的查找也非常简单了,假如我们要查找元素6,先从根部出发,因为6>5,故应该在右子树中找,而在右子树中,6<8,在左子树中找,找到了。如果找到null指针,则说明该元素不在二叉查找树中。

下面是查找的代码:

 

void search(int element,Node *p)
{
	if(p==NULL)
		return; //元素不在树中
	if(element== p->value)
		cout << "found "<value)//左子树递归查找
		search(element,p->leftChild);
	else      //if element > p->value 右子树递归查找
		search(element,p->rightChild);
}

【小结】

由于树的递归结构,我们可以很方便地使用递归的思想,而我们也可能为了效率而避免使用递归,而使用迭代的方法提高效率。还是继续看珠玑吧。

by bibodeng 2012-05-17   原载于bibodeng think beyond