一步一步写算法(之哈希二叉树)

原文:一步一步写算法(之哈希二叉树)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

    用过平衡二叉树的朋友都清楚,平衡二叉树的最大优点就是排序。不管是在数据插入的时候还是在数据删除的时候,我们都要考虑到数据的排序情况。但是和数据的添加、删除一样重要的,还有数据的查询。很不幸,平衡二叉树经常由于节点的添加和删除,数据的查询效率会变得非常低下。朋友们可以看看下面这样的一个极端场景,所有分支节点都只有一边存在数据:

/*
*         7        3
*        /           \
*       6             4
*      /                \
*     5                  7
*    /                    \
*   2                     12
*  /                        \
* 1                         20
*/

    上面的这幅图很能说明问题,虽然查询7、6很方便,但是查询5、2、1的时候效率就非常低了,右边的二叉树也是这种情况。那么有没有办法使得数据之间的查找效率不至于相差太大呢?截止目前为止,主要有下面三种方法:

    (1)哈希二叉树

    (2)avl树

    (3)红黑树

     今天我们主要讲解的内容就是哈希树。其他两个内容会在后面的博客里面介绍。

    那么什么是哈希树呢?其实也非常简单,就是我们在二叉树节点中添加一个next指针,同时建立一个hash表,这样我们在查询数据的时候就可以直接利用hash查询代替平衡二叉树的查询了。一般来说,哈希树的节点应该是这样定义的:

typedef struct _HASH_TREE
{
	int data;
	struct _HASH_TREE* next;
	struct _HASH_TREE* left;
	struct _HASH_TREE* right;
}HASH_TREE;

    其实,相比较普通的平衡二叉树而言,也就是多了一个next指针而已,那么这个next指针什么时候需要处理呢?主要就是在添加节点和删除节点的时候处理。

STATUS add_node_into_tree(HASH_TREE** ppHash, int data)
{

	/* add hash node into tree */

	/* add hash node into hash table */

	return TRUE;
}

    添加的代码如此,删除工作也比较类似。

STATUS delete_node_from_tree(HASH_TREE** ppHash, int data)
{
	HASH_TREE* pNode;
	/* delete hash node from tree, but not free space*/

	/* delete hash node from hash table */

	free(pNode);
	return TRUE;
}

说明:

    (1)哈希二叉树的思想比较重要,同学们最好弄清楚为什么要建立hash二叉树?

    (2)上面的代码不是很完整,对hash表不熟悉的朋友可以参考我写的这一篇博客(hash表),二叉树添加删除不熟悉的朋友同样可以参考我写的另外一篇博客(添加删除1删除2删除3),把两部分代码按照上面给出的结构合起来基本上就可以实现哈希二叉树了。

时间: 2024-09-16 10:53:50

一步一步写算法(之哈希二叉树)的相关文章

一步一步写算法(之排序二叉树线索化)

原文:一步一步写算法(之排序二叉树线索化) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     前面我们谈到了排序二叉树,还没有熟悉的同学可以看一下这个,二叉树基本操作.二叉树插入.二叉树删除1.删除2.删除3.但是排序二叉树也不是没有缺点,比如说,如果我们想在排序二叉树中删除一段数据的节点怎么办呢?按照现在的结构,我们只能一个一个数据查找验证,首先看看在不在排序二叉树中,如果在那么删除:如果没有这个数据,那么继续查找.那么有没有方法

一步一步写算法(之排序二叉树删除-1)

原文:一步一步写算法(之排序二叉树删除-1) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     相比较节点的添加,平衡二叉树的删除要复杂一些.因为在删除的过程中,你要考虑到不同的情况,针对每一种不同的情况,你要有针对性的反应和调整.所以在代码编写的过程中,我们可以一边写代码,一边写测试用例.编写测试用例不光可以验证我们编写的代码是否正确,还能不断提高我们开发代码的自信心.这样,即使我们在开发过程对代码进行修改或者优化也不会担心害怕.

一步一步写算法(之排序二叉树)

原文:一步一步写算法(之排序二叉树) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点.它是这样定义的: typedef struct _TREE_NODE { int data; struct _TREE_NODE* parent;

一步一步写算法(之排序二叉树的保存和加载)

原文:一步一步写算法(之排序二叉树的保存和加载)[ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     排序二叉树是我们开发中经常使用到的一种数据结构,它具有较好的插入.删除.查找特性.但是由于二叉树的指针较多,所以相比较其他的数据结构而言,二叉树来得比较麻烦些.但是也不是没有办法,下面介绍一下我个人常用的方法.     我们知道,如果一个二叉树是一个满树的话,那么二叉树的节点应该是按照1.2.3.4依次排开的.但是现实情况是这样的,由于

一步一步写算法(之排序二叉树插入)

原文:一步一步写算法(之排序二叉树插入) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     二叉树的节点插入比较简单.一般来说,二叉树的插入主要分为以下两个步骤:     1) 对当前的参数进行判断,因为需要考虑到头结点,所以我们使用了指针的指针作为函数的输入参数     2) 分情况讨论:         如果原来二叉树连根节点都没有,那么这个新插入的数据就是根节点:         如果原来的二叉树有根节点,那我们判断这个数据是

一步一步写算法(之排序二叉树删除-2)

原文:一步一步写算法(之排序二叉树删除-2) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     2.4 删除节点的左右子树都存在,此时又会分成两种情形     1)左节点是当前左子树的最大节点,此时只需要用左节点代替根节点即可 /* * * 10 ======> 6 * / \ / \ * 6 15 5 15 * / * 5 */     代码该怎么编写呢? STATUS delete_node_from_tree(TREE_NOD

一步一步写算法(之排序二叉树删除-3)

原文:一步一步写算法(之排序二叉树删除-3) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     3 普通节点的删除     3.1 删除的节点没有左子树,也没有右子树      测试用例1: 删除节点6 /* * * 10 ======> 10 * / \ \ * 6 15 15 * */ static void test8() { TREE_NODE* pTreeNode = NULL; assert(TRUE == insert

一步一步写算法(之二叉树深度遍历)

原文:一步一步写算法(之二叉树深度遍历) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     深度遍历是软件开发中经常遇到的遍历方法.常用的遍历方法主要有下面三种:(1)前序遍历:(2)中序遍历:(3)后序遍历.按照递归的方法,这三种遍历的方法其实都不困难,前序遍历就是根-左-右,中序遍历就是左-根-右,后续遍历就是左-右-根.代码实现起来也不复杂.     1)前序遍历 void preorder_traverse(TREE_NOD

一步一步写算法(之克鲁斯卡尔算法 下)

原文:一步一步写算法(之克鲁斯卡尔算法 下) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     前面在讨论克鲁斯卡尔的算法的时候,我们分析了算法的基本过程.基本数据结构和算法中需要解决的三个问题(排序.判断.合并).今天,我们继续完成剩下部分的内容.合并函数中,我们调用了两个基本函数,find_tree_by_index和delete_mini_tree_from_group,下面给出详细的计算过程. MINI_GENERATE_T

一步一步写算法(之线性结构的处理)

原文:一步一步写算法(之线性结构的处理) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     我们知道,在内存中的空间都是连续的.也就是说,0x00000001下面的地址必然是0x00000002.所以,空间上是不会出现地址的突变的.那什么数据结构类型是连续内部空间呢,其实就是数组,当然也可以是堆.数组有很多优势,它可以在一段连续空间内保存相同类型的数据,并且对这些数据进行管理.所以从这个意义上说,掌握了数组才能说明你数据结构入门了.