📜  数据结构概述 |设置 2(二叉树、BST、堆和哈希)

📅  最后修改于: 2021-10-28 01:26:43             🧑  作者: Mango

我们已经讨论了数组、链表、队列和堆栈的概述。本文将讨论以下数据结构。

5. 二叉树
6. 二叉搜索树
7. 二叉堆
9. 散列

二叉树
与数组、链表、堆栈和队列这些线性数据结构不同,树是分层数据结构。
二叉树是一种树数据结构,其中每个节点最多有两个孩子,分别称为左孩子和右孩子。它主要使用链接来实现。

二叉树表示:树由指向树中最顶层节点的指针表示。如果树为空,则 root 的值为 NULL。二叉树节点包含以下部分。
1. 数据
2. 指向左孩子的指针
3. 指向右孩子的指针

二叉树可以通过两种方式遍历:
深度优先遍历:中序(Left-Root-Right)、前序(Root-Left-Right)和后序(Left-Right-Root)
广度优先遍历:层序遍历

二叉树属性:

The maximum number of nodes at level ‘l’ = 2l.

Maximum number of nodes = 2h + 1 – 1.
Here h is height of a tree. Height is considered 
as the maximum number of edges on a path from root to leaf.

Minimum possible height =  ceil(Log2(n+1)) - 1  

In Binary tree, number of leaf nodes is always one 
more than nodes with two children.

Time Complexity of Tree Traversal: O(n)

示例:一般使用二叉树或树的一个原因是用于形成层次结构的事物。它们在文件结构中很有用,其中每个文件都位于特定目录中,并且存在与文件和目录相关联的特定层次结构。树有用的另一个例子是存储分层对象,如 JavaScript 文档对象模型将 HTML 页面视为一棵树,标签嵌套作为父子关系。

二叉搜索树
在二叉搜索树中,二叉树具有以下附加属性:
1. 节点的左子树只包含键小于节点键的节点。
2. 节点的右子树只包含键值大于节点键值的节点。
3.左右子树也必须是二叉搜索树。

时间复杂度:

Search :  O(h)
Insertion : O(h)
Deletion : O(h)
Extra Space : O(n) for pointers

h: Height of BST
n: Number of nodes in BST

If Binary Search Tree is Height Balanced, 
then h = O(Log n) 

Self-Balancing BSTs such as AVL Tree, Red-Black
Tree and Splay Tree make sure that height of BST 
remains O(Log n)

BST 提供适度的访问/搜索(比链表快,比数组慢)。
BST 提供适度的插入/删除(比数组快,比链表慢)。

示例:它的主要用途是在搜索应用程序中,数据不断进入/离开,数据需要按排序顺序打印。例如,在电子商务网站的实施中,添加了新产品或产品缺货,并且所有产品都按排序顺序列出。

二叉堆
二叉堆是具有以下属性的二叉树。
1)它是一棵完整的树(所有级别都被完全填充,除了最后一个级别,最后一个级别尽可能保留所有键)。二叉堆的这个特性使得它们适合存储在数组中。
2) 二叉堆是最小堆或最大堆。在最小二叉堆中,根处的键必须是二叉堆中所有键中的最小值。对于二叉树中的所有节点,相同的属性必须递归为真。 Max Binary Heap 类似于 Min Heap。它主要是使用数组来实现的。

Get Minimum in Min Heap: O(1) [Or Get Max in Max Heap]
Extract Minimum Min Heap: O(Log n) [Or Extract Max in Max Heap]
Decrease Key in Min Heap: O(Log n)  [Or Decrease Key in Max Heap]
Insert: O(Log n) 
Delete: O(Log n)

示例:用于实现高效的优先级队列,而优先级队列又用于调度操作系统中的进程。 Dijikstra 和 Prim 的图算法中也使用了优先队列。
Heap 数据结构可用于高效地查找数组中的 k 个最小(或最大)元素、合并 k 个排序数组、流的中值等。
堆是一种特殊的数据结构,它不能用于搜索特定元素。

HashingHash函数:一个函数转换给定的输入大关键是一个小的实用整数值。映射的整数值用作哈希表中的索引。一个好的散列函数应该具有以下属性
1) 可有效计算。
2) 应该均匀分配钥匙(每个桌子位置每个钥匙的可能性相同)

哈希表:存储指向与给定电话号码对应的记录的指针的数组。如果没有现有电话号码具有等于条目索引的哈希函数值,则哈希表中的条目为 NIL。

冲突处理:由于散列函数我们提供了一个大整数或字符串键的小数字,因此两个键可能会产生相同的值。新插入的键映射到哈希表中已占用槽的情况称为冲突,必须使用某种冲突处理技术进行处理。以下是处理碰撞的方法:

链式:思想是让哈希表的每个单元格都指向一个具有相同哈希函数值的记录的链表。链接很简单,但需要额外的表外内存。
开放寻址:在开放寻址中,所有元素都存储在哈希表本身中。每个表条目包含一条记录或 NIL。在搜索元素时,我们会逐个检查表槽,直到找到所需元素或明确该元素不在表中。

Space : O(n)
Search    : O(1) [Average]    O(n) [Worst case]
Insertion : O(1) [Average]    O(n) [Worst Case]
Deletion  : O(1) [Average]    O(n) [Worst Case]

对于所有操作,散列似乎比 BST 更好。但是在散列中,元素是无序的,而在 BST 中,元素以有序的方式存储。此外,BST 易于实现,但哈希函数有时生成起来非常复杂。在 BST 中,我们还可以有效地找到值的下限和上限。

示例:散列可用于从一组元素中删除重复项。也可用于查找所有项目的频率。例如,在 Web 浏览器中,我们可以使用哈希检查访问过的 url。在防火墙中,我们可以使用散列来检测垃圾邮件。我们需要散列IP地址。哈希可用于任何需要在 O(1) 时间内进行 search()、insert() 和 delete() 的情况。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程