今日はいくつかの質問を練習しました。そのうちの2つを以下に要約します。
これら2つのトピックの基本的な考え方は同じで、1つは大きな根の山で、もう1つは小さな根の山です。
ビッグルートヒープの問題:配列
内でK番目に大きい要素。実際、この問題は他の基本的で一般的な並べ替え方法で解決できますが、ここでは、ヒープ並べ替えに基づいて方法を選択します。
我们也可以使用堆排序来解决这个问题——建立一个大根堆。
做 k - 1 次删除操作后堆顶元素就是我们要找的答案。
部分代码如下:
void maxHeapify(int* a, int i, int heapSize) {
int l = i * 2 + 1, r = i * 2 + 2, largest = i;//l是左孩子,r是右孩子
if (l < heapSize && a[l] > a[largest]) {
//左孩子存在且左孩子大于该结点值
largest = l;
}
if (r < heapSize && a[r] > a[largest]) {
//右孩子存在且右孩子大于该结点值
largest = r;
}
if (largest != i) {
//不相等则是调整过
int t = a[i];
a[i] = a[largest];
a[largest] = t;
maxHeapify(a, largest, heapSize);//对调整交换后的结点继续进行调整
}
}
void buildMaxHeap(int* a, int heapSize) {
for (int i = heapSize / 2; i >= 0; --i) {
//i = heapSize / 2的意义是从倒着数第一个非叶子结点的结点开始建堆
maxHeapify(a, i, heapSize);
}
}
int findKthLargest(int* nums, int numsSize, int k) {
int heapSize = numsSize;
buildMaxHeap(nums, heapSize);//调整第一次
for (int i = numsSize - 1; i >= numsSize - (k - 1); --i) {
//求第k大,再调整k-1次
int t = nums[0];
nums[0] = nums[i];
nums[i] = t;
--heapSize;//去除首项,将末项放在首项,下面进行堆调整
maxHeapify(nums, 0, heapSize);
}
return nums[0];//调整k-1次后最大的
}
小さな根の山の問題:kの最小数は
、2つの問題に対して従来の方法を使用することは実際には難しくありません。問題を理解すると、実際には性質が同じであり、この方法で実現できることがわかります。ヒープソートに基づいています。この問題は前の問題と同じです。ここでは小さなルートパイルが使用されていることを除いて、基本的に同じです。
void minHeapify(int* a, int i, int heapSize) {
int l = i * 2 + 1, r = i * 2 + 2, largest = i;//l是左孩子,r是右孩子
if (l < heapSize && a[l] < a[largest]) {
//左孩子存在且左孩子小于该结点值
largest = l;
}
if (r < heapSize && a[r] < a[largest]) {
//右孩子存在且右孩子小于该结点值
largest = r;
}
if (largest != i) {
//不相等则是调整过
int t = a[i];
a[i] = a[largest];
a[largest] = t;
minHeapify(a, largest, heapSize);//对调整交换后的结点继续进行调整
}
}
void buildMinHeap(int* a, int heapSize) {
for (int i = heapSize / 2; i >= 0; --i) {
//i = heapSize / 2的意义是从倒着数第一个非叶子结点的结点开始建堆
minHeapify(a, i, heapSize);
}
}
int* getLeastNumbers(int* arr, int arrSize, int k, int* returnSize){
int heapSize = arrSize;
int*mn=(int*)malloc(sizeof(int)*k);
*returnSize=k;
if(k==0)return mn;
int p=0;
buildMinHeap(arr, heapSize);
mn[p++]=arr[0];//这里因为上面已经调整好一次,所以给mn加入一个值
for (int i = arrSize - 1; i >= arrSize - (k - 1); --i) {
//再调整k-1次
int t = arr[0];
arr[0] = arr[i];
arr[i] = t;
--heapSize;//去除首项,将末项放在首项,下面进行堆调整
minHeapify(arr, 0, heapSize);
mn[p++]=arr[0];//每调整好一次,为mn添一个值
}
return mn;
}
これらの2つのトピックはそれ自体が単純であり、プログラムは単純で理解しやすいため、ヒープソートの調整プロセスとその基本的な考え方を誰もが理解するのに役立ちます。