算法精解(七):C語言描述(二叉搜索樹)

二叉樹搜索樹概念

  二叉搜索樹是由二叉樹組成的專用於查找和搜索的一種數據結構。需要在二叉樹中查詢一個節點,從根節點開始一層層往下查找,直到找到目標節點爲止。當遇到一個比目標節點值大的節點時,順着該節點的左子樹繼續查找。如果遇到的節點值小於目標節點,則順着該節點的右子樹繼續查找。(左分支的數,一定小於右分支的數,個人覺得類似二分查找)

   二叉搜索樹是一種用於查找操作的高效數據結構,最壞情況只需查找一個分支 的數據即可,而不用檢索所有數據,所以操作的複雜度爲O(lg n).

代碼實現

#include"bitree.h"
typedef BiTree BisTree;
//初始化二叉搜索樹,compare用於比較key1>key2?1:-1(= 0)
void bistree_init(BisTree *tree, void(*compare)(const void *key1, const void *key2),
	void(*destroy)(void *data));

//銷燬樹
void bistree_destroy(BisTree *tree);

//插入節點,成功返回0,要插入的節點已存在返回1,否則-1
int bistree_insert(BisTree *tree, const void *data);   //複雜度lg n

//移除等於data的節點,成功返回0,否則-1
int bistree_remove(BisTree *tree, const void *data);   //複雜度lg n

//查找對應data的節點,成功返回0,否則-1
int bistree_lookup(const BisTree *tree, void **data);  //複雜度lg n

//銷燬node節點開始的左分支
static void destroy_right(BisTree *tree, BiTreeNode *node);
static void destroy_left(BisTree *tree, BiTreeNode *node)
{
	BiTreeNode **position;
	if (tree->size == 0) return;   //如果樹節點爲0 ,直接返回
	if (node == NULL)    //如果node爲null,從根節點開始刪除
		position = &tree->root;
	else
		position = &node->left;

	if (*position != NULL)
	{
		//遞歸消除position開始的左右子樹
		destroy_left(tree, *position);
		destroy_right(tree, *position);
		if (tree->destroy != NULL)
		{
			//調用析構函數;
		}

		//釋放節點空間,size--
		free((*position)->data);
		free(*position);
		*position = NULL;
		tree->size--;
	}
	return;
}

//在樹tree的node節點開始插入data數據
static int insert(BisTree *tree, BiTreeNode **node, const void *data)
{
	int cmpval, retval;
	if (bitree_is_eob(*node))   //如果指定節點沒有左右節點,從左節點開始插入
	{
		return bitree_ins_left(tree, *node, data);
	}
	else
	{
		cmpval = tree->compare(data, (*node)->data);   //比較node->data和data的值,data大時,右子樹插入
		if (cmpval < 0)
		{
			if (bitree_is_eob((*node)->left)) //如果node->left爲空
			{
				if (bitree_ins_left(tree, *node, data) != 0)
					return -1;
			}
			else
			{
				if ((retval = insert(tree, &((*node)->left), data)) != 0)
				{
					return retval;
				}
			}
		}
		else if(cmpval > 0)
		{
			if (bitree_is_eob((*node)->right)) //如果node->left爲空
			{
				if (bitree_ins_right(tree, *node, data) != 0)
					return -1;
			}
			else
			{
				if ((retval = insert(tree, &((*node)->right), data)) != 0)
				{
					return retval;
				}
			}
		}
		else  //如果node->data == data,則爲數據衝突
		{
			if (tree->destroy != NULL)
				tree->destroy((*node)->data);
			(*node)->data = data;   //此處,不能講const data賦值給*node->data
		}
	}
	return 0;
}

//在樹tree的node節點開始查找data數據
static int lookup(BisTree *tree, BiTreeNode *node,const void **data)
{
	int cmpval, retval;
	if (bitree_is_eob(node)) //node的左右節點不爲空
	{
		return -1;
	}

	//比較插入節點和要插入數據的值
	cmpval = tree->compare(*data, node->data);

	if (cmpval < 0)   //如果插入數據小於node->data,在node的左子樹尋找位置繼續比較
		retval = lookup(tree, node->left, data);
	else if (cmpval > 0)  //如果插入數據大於node->data,在node的右子樹尋找位置繼續比較
		retval = lookup(tree, node->right, data);
	else   //等於時,取出數據
	{ 
		*data = node->data;
	}

	return retval;
}

void bistree_init(BisTree *tree, int(*compare)(const void *key1, const void *key2), void(*destroy)(void *data))
{
	bitree_init(tree, destroy);
	tree->compare = compare;
	return;
}

void bistree_destroy(BisTree *tree)
{
	destroy_left(tree, NULL);
	memset(tree, 0, sizeof(BisTree));
	return;
}

int bistree_insert(BisTree *tree, const void *data)
{
	return insert(tree, &(tree->root), data);
}

int bistree_remove(BisTree *tree, const void *data)
{
	return lookup(tree, tree->root, &data);
}

int bistree_lookup(BisTree *tree, void **data)
{
	return lookup(tree, tree->root, data);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章