1. 插入
为了把元素x插入到堆H中,先将堆大小加1,然后将x添加到H的末尾,再根据需要,把x上移,直到满足堆特性。
如果n是新堆的大小,那么堆树的高度是⌊log n⌋,所以将一个元素插入大小为n的堆中所需要的时间是O(log n)。
过程 Insert
输入 堆H[1...n]和元素x
输出 新的堆H[1...n+1],x为其元素之一
算法描述
n ← n+1 {增加H的大小}
H[n] ← x
Sift-up(H, n)
注意这里算法描述的数组的索引都是1...n,而不是大家习惯的0...n-1。
// heap[0]用来存储数组中堆数据的长度,堆数据heap[1]...heap[heapLength]
// 所以数组的实际长度是heapLength+1,我们只对从数组索引为1开始的heapLength个数据进行操作
int* insertElement(int* heap, int element)
{
int heapLength = heap[0];
int resultHeapLength = heapLength + 1;
// 创建一个长度为resultHeapLength+1的int数组
int* resultHeap = (int*)malloc(sizeof(heap) * (resultHeapLength + 1));
if (resultHeap == NULL)
return NULL;
resultHeap[0] = resultHeapLength;
for (int i = 1; i <= heapLength; i++)
{
resultHeap[i] = heap[i];
}
resultHeap[resultHeapLength] = element;
siftUp(resultHeap, resultHeapLength);
return resultHeap;
}
2. 删除
要从大小为n的堆H中删除元素H[i],可先用H[n]替换H[i],然后将堆栈大小减1,如果需要的话,根据H[i]的键值与存储在它父节点和子节点中元素键值的关系,对H[i]做Sift-up或Sift-down运算,直到满足堆特性为止。
堆树的高度是⌊log n⌋,所以从一个大小为n的堆栈中删除一个元素所需要的时间是O(log n)。
过程 Delete
输入 非空堆H[1...n]和位于1和n之间的索引i
输出 删除H[i]之后的新堆H[1...n-1]
算法描述
x ← H[i]; y ← H[n]
n ← n-1 {减小H的大小}
if i = n+1 then exit {完成}
H[i] ← y
if key(y) ≥ key(x) then Sift-up(H, i)
else Sift-down(H, i)
end if
注意这里算法描述的数组的索引也都是1...n,而不是大家习惯的0...n-1。
// heap[0]用来存储数组中堆数据的长度,堆数据heap[1]...heap[heapLength]
// 所以数组的实际长度是heapLength+1,我们只对从数组索引为1开始的heapLength个数据进行操作
int* deleteElement(int* heap, int index)
{
int heapLength = heap[0];
if (index < 1 || index > heapLength)
return heap;
int x = heap[index];
int y = heap[heapLength];
int resultHeapLength = heapLength - 1;
// 创建一个长度为resultHeapLength+1的int数组
int* resultHeap = (int*)malloc(sizeof(heap) * (resultHeapLength + 1));
if (resultHeap == NULL)
return NULL;
resultHeap[0] = resultHeapLength;
for (int i = 1; i <= resultHeapLength; i++)
{
resultHeap[i] = heap[i];
}
if (index == resultHeapLength)
return resultHeap;
resultHeap[index] = y;
if (y > x)
{
siftUp(resultHeap, index);
}
else
{
siftDown(resultHeap, index);
}
return resultHeap;
}
我使用的数组是这样定义的:
const int HEAP_LENGH = 10;
int heap[HEAP_LENGH + 1] = { HEAP_LENGH, 20, 11, 9, 10, 5, 4, 5, 3, 7, 3 };
// 如果用我上面写的方法插入删除数据,不要忘了在操作完成之后释放内存哦
int* heapAfterInsert = insertElement(heap, 30);
int* heapAfterDelete = deleteElement(heapAfterInsert, 2);
free(heapAfterDelete);
free(heapAfterInsert);
更多内容请参考:
算法 之 堆 - 简介
算法 之 堆 - Sift-up和Sift-down
分享到:
相关推荐
链表分为单链表、双链表和循环链表等类型,提供了灵活的插入和删除操作。 3. **栈**:栈是一种后进先出(LIFO)的数据结构,常用于函数调用、表达式求值等场景。C++中的`std::stack`库提供了栈操作的实现。 4. **...
链表则允许动态插入和删除,适合内存管理;队列遵循先进先出(FIFO)原则,常见于任务调度;栈则是后进先出(LIFO)模型,常用于函数调用和表达式求值。 2. 树形数据结构:如二叉树、平衡树(AVL树、红黑树)和堆。...
- **散列表(Hash Tables)**:章节11介绍了散列表的概念及其应用,包括散列函数的设计、冲突解决策略等,散列表在平均情况下的查找、插入和删除操作时间复杂度均为O(1)。 - **二叉搜索树(Binary Search Trees)**...
3. **图论与树**:可能包含图的遍历(深度优先搜索和广度优先搜索)、最小生成树(如Prim或Kruskal算法)以及二叉树的操作,如插入、删除和查找。 4. **动态规划**:这是解决许多复杂问题的有效方法,例如背包问题...
本文将详细讲解堆的初始化、插入、删除操作,以及使用C++实现的堆排序算法。 首先,堆是一种完全二叉树,可以分为最大堆和最小堆。在最大堆中,每个节点的值都大于或等于其子节点的值;在最小堆中,每个节点的值都...
该书不仅详细介绍了算法的基本概念、原理和设计策略,还提供了大量的实例分析和实践应用,使其成为计算机科学领域不可或缺的经典之作。 ### 知识点解析 #### 1. 算法基础知识 - **定义与分类**:书中首先对算法...
基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,...
算法是解决问题的步骤,可以分为排序算法(如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等)、搜索算法(如深度优先搜索、广度优先搜索)、图算法(如最短路径问题的Dijkstra算法、Floyd-Warshall...
《数据结构与算法之美》是王争先生撰写的一部深入浅出的数据结构和算法学习资料。这个压缩包可能包含了该专栏的资源文件“ljg_resource1”,虽然具体内容未知,但我们可以根据通常的数据结构和算法的学习内容进行...
书中涉及到的知识点包括算法分析,列表,栈和队列,树,哈希,优先队列(堆),排序算法,离散集ADT,图算法,算法设计技术,摊还分析,以及高级数据结构和实现等。 算法分析是研究算法性能的过程,它包括时间...
以下是B-树的基本概念、查找算法、插入算法和删除算法的详细说明。 **基本概念:** B-树是一种m阶的树,意味着每个节点最多有m个孩子。在B-树中,节点包含关键字和指向子节点的指针。节点中的关键字按照升序排列,...
书中可能涵盖排序算法(如冒泡排序、选择排序、插入排序、快速排序、归并排序和堆排序)、搜索算法(如线性搜索、二分搜索、深度优先搜索和广度优先搜索)、图算法(如Dijkstra算法、Floyd-Warshall算法、Prim算法和...
5. **排序算法**:排序是将无序序列转变为有序序列的过程,包括冒泡排序、插入排序、选择排序、快速排序、归并排序和堆排序等。不同的排序算法有不同的时间复杂度和适用场景,比如快速排序在平均情况下效率较高,而...
它们在查找、插入和删除操作中具有良好的性能。堆通常用于优先队列,可以快速找到最大或最小元素。图则用于表示复杂的关系,如网络路由、社交网络等,常见的图算法有深度优先搜索(DFS)和广度优先搜索(BFS)。 ...
在本书中,你将学习到排序算法(如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序)、搜索算法(线性搜索、二分搜索)、图算法(深度优先搜索、广度优先搜索)、动态规划以及贪心算法等。这些算法不仅...
算法是数据结构的灵魂,常见算法如排序(冒泡、选择、插入、快速、归并、堆排序等)和搜索(顺序、二分、哈希)。C++中,算法通常作为独立的头文件提供,如`<algorithm>`,方便开发者直接调用。 在实际应用中,理解...
数据结构是计算机科学中的核心课程,它探讨了如何在计算机中有效地存储和组织数据,以便进行高效的检索、插入和删除等操作。C++语言作为面向对象的编程语言,提供了丰富的特性和工具,使得实现复杂的数据结构算法变...
排序算法如冒泡排序、选择排序、插入排序、快速排序、归并排序和堆排序,各有其适用场景和优缺点。搜索算法有线性搜索、二分搜索以及哈希表搜索等,其中二分搜索适用于有序数据,而哈希表搜索则提供近乎常数时间的...