什么是二叉搜索树
树是一种数据结构,它要么为空,要么具有一个值并具有零个或多个节点,每个结点本身也是树。
二叉树是树的一种特殊形式,它的每个节点至多具有两个节点,分别称为左结点和右结点。二叉搜索树具有一个额外的属性:每个节点的值比它的左子树的所有节点的值都要大,但比它的右子树的所有节点的值都要小。这个定义排除了树中存在值相同的节点的可能性。这使树成为一种用关键值快速查找数据的优秀工具。
二叉搜索树的每个节点都具有一个上层节点,零个、一个或两个子节点。唯一例外的是根节点,它没有上层节点。没有子节点的节点被称为叶节点或叶子。树的根位于顶端,叶子位于底部。
二叉搜索树的操作
-
插入
当一个新值添加到树时,它必须被放在合适的位置。基本算法如下:
-
删除
从树中删除一个值比较困难,因为要考虑到树之间的关联。
我们必须处理三种情况:删除没有子节点的节点;删除只有一个子节点的节点;删除有两个子节点的节点。第1种情况很简单,删除一个叶节点不会导致任何子树断开,所有不存在重新连接的问题。删除只有一个子节点的节点也不难,把这个节点的上层节点和它的子节点连接起来就可以了。最后一种情况要困难得多。如果一个节点有两个子节点,它的上层节点不能连接到它的两个子节点。解决这个问题的一种方法是不删除这个节点,而是删除它的左子树中值最大的那个节点,并用这个值代替原先应被删除的那个节点的值。 -
查找
在树中查找一个特定的值非常容易。
这个递归算法也属于尾部递归,所以采用迭代方案来实现效率更高。 -
遍历
当你检查一棵树的所有节点时,你就在遍历这棵树。遍历树的节点有几种不同的次序,最常用的是前序、中序、后序和层次遍历。所有类型的遍历都是从树的根节点或你希望开始遍历的子树的根节点开始。
前序遍历检查节点的值,然后递归地遍历左子树和右子树。当检查每个节点时打印出它的值,那么它的前序遍历的输出结果将是:20,12,5,9,16,17,25,28,26,29。
中序遍历首先遍历左子树,然后检查当前节点的值,最后遍历右子树。输出结果是:5,9,12,16,17,20,25,26,28,29。
后序遍历首先遍历左右子树,然后检查当前节点的值。结果是:9,5,17,16,12,26,29,28,25,20。
最后,层次遍历逐层检查树的节点。首先处理根节点,接着是它的子节点,再接着是子节点的子节点,依次类推。输出结果是:20,12,25,5,16,28,9,17,26,29。虽然前三种遍历方法可以很容易地使用递归来实现,但最后这种层次遍历要采用一种使用队列的迭代算法。
二叉搜索树接口
tree.h
/*
* Binary search tree module interface
*/
#define TREE_TYPE int /* The value type of the tree */
/*
* insert
* Adds a new value to the tree. A parameter is a value that needs to be added;
* it must not have existed in the tree before.
*/
void insert(TREE_TYPE value);
/*
* find
* Finds a specific value that is passed to the function as the first argument.
*/
TREE_TYPE *find(TREE_TYPE value);
/*
* pre_order_traverse
* Performs a pre-order traversal of the tree, which takes a callback function
* pointer that points to the function that will handle the tree. Each node is
* called, and the value of