姓名:毛浩 学号:17029250003
【嵌牛导读】一道力扣题。
【嵌牛鼻子】力扣
【嵌牛提问】如何解决同位异构词
【嵌牛正文】
堆与堆排序
@(数据结构)[堆||排序]
以下代码不敢保证均对,须自己验证
[TOC]
二叉堆的定义
二叉堆是完全二叉树或者是近似完全二叉树。
二叉堆满足两个特性:
- 父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
-
每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。下图展示一个最小堆:
1.png
堆的存储
一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。
堆的操作
![](https://img.haomeiwen.com/i25094341/6308bd80793a05ae.png)
堆的插入
每次插入都是将新数据插入到数组末尾,在插入之前数组即为有序数组,现在的任务相当于将一个数插入到有序数组中,一个插入排序算法如下:
void MinHeapFixup(int a[], int i){
int j, tmp;
tmp = a[i];
j = (i - 1) / 2;//父节点
while(j >= 0 && i != 0){
if(a[j] < tmp)
break;
a[i] = a[j];
i = j;
j = (i - 1) / 2;
}
a[i] = tmp;
}
更简短的表达为:
void MinHeapFixup(int a[], int i){
for(int j=(i-1)/2; j>=0 && a[i]>a[j]; i=j, j=(i-1)/2){
swap(a[i], a[j]);
}
}
堆的删除
按定义,堆中每次都只能删除第0个数据。为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,然后再从根结点开始进行一次从上向下的调整。调整时先在左右儿子结点中找最小的,如果父结点比这个最小的子结点还小说明不需要调整了,反之将父结点和它交换后再考虑后面的结点。相当于从根结点将一个数据的“下沉”过程。下面给出代码:
// 从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
void MinHeapFixdown(int a[], int i, int n)
{
int k, j;
for (j = 2 * i + 1, k = i; j < n; k = j, j = 2 * j + 1)
{
if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
j++;
if (a[j] >= a[k])
break;
Swap(a[k], a[j]);
}
}
//在最小堆中删除数
void MinHeapDeleteNumber(int a[], int n)
{
Swap(a[0], a[n - 1]);
MinHeapFixdown(a, 0, n - 1);
}
网友评论