目录
1. 堆排序
创建一个大小为k的小顶堆,确保nums[0]是k个元素中最小,是numsSize个元素中第k大,如果有其他元素大于堆顶元素nums[0]则交换,并更新堆。
如何更新堆?
堆是完全二叉树,在数组中存储,i是孩子节点,i/2就是父节点,小顶堆中父节点要小于子节点,因此用
for(int i=k-1;i>0;i--){
if(nums[i]<nums[i/2]) 对所有子节点和父节点进行比较。
void swap(int *nums,int i,int j){
int tmp=nums[i];
nums[i]=nums[i/2];
nums[i/2]=tmp;
}
void update(int *nums,int k){
for(int i=k-1;i>0;i--){
if(nums[i]<nums[i/2]){
swap(nums,i,i/2);
}
}
}
int findKthLargest(int* nums, int numsSize, int k){
if(numsSize==0)return ;
update(nums,k);
for(int i=k;i<numsSize;i++){
if(nums[i]>nums[0]){
nums[0]=nums[i];
update(nums,k);
}
}
return nums[0];
}
2. 优先队列
入队:把节点放在最后一个,进行堆更新
q->table[q->Size] = en;
q->Size++;
priority_queue_adjust(q);
出队:保存用于返回的头节点,并将最后一个节点放置于头节点处,进行堆更新
en = q->table[0];
q->table[0] = q->table[q->Size - 1];
q->Size--;
priority_queue_adjust(q);
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int key;
char* value;
}Element;
typedef struct
{
int Capacity;
int Size;
Element** table;
}PriorityQueue;
void swap(Element** table, int i, int j);
PriorityQueue* priority_queue_initialize(int capacity);
void queue_free(PriorityQueue* q);
const Element* priority_queue_top(PriorityQueue* q);
Element* priority_queue_dequeue(PriorityQueue* q);
priority_queue_enqueue(PriorityQueue* q, int key, char* value);
priority_queue_adjust(PriorityQueue* q);
Element* CreateElement(int key, char* value);
#include "priority_queue.h"
static void priority_queue_realloc(PriorityQueue* q);
void swap(Element** table, int i, int j) {
Element* temp = table[i];
table[i] = table[j];
table[j] = temp;
}
PriorityQueue* priority_queue_initialize(int capacity) {
PriorityQueue* q = malloc(sizeof(*q));
if (q != NULL) {
q->Capacity = capacity;
q->Size = 0;
q->table = (Element**)malloc(sizeof(Element*) * q->Capacity);
}
return q;
}
void queue_free(PriorityQueue* q) {
for (int i = 0; i < q->Size; i++) {
//free(q->table[i]->value);
free(q->table[i]);
}
free(q->table);
free(q);
}
const Element* priority_queue_top(PriorityQueue* q) {
if (q->Size > 0)return q->table[0];
return NULL;
}
Element* priority_queue_dequeue(PriorityQueue* q) {
Element* en = NULL;
if (q->Size > 0) {
en = q->table[0];
q->table[0] = q->table[q->Size - 1];
q->Size--;
priority_queue_adjust(q);
}
return en;
}
priority_queue_enqueue(PriorityQueue* q,int key,char *value) {
Element* en = malloc(sizeof(*en));
if(en!=NULL){
en->key = key;
en->value = value;
q->table[q->Size] = en;
q->Size++;
priority_queue_adjust(q);
if (q->Size >= q->Capacity) {
priority_queue_realloc(q);
}
}
}
priority_queue_adjust(PriorityQueue* q) {
for (int i = q->Size - 1; i > 0; i--) {
if (q->table[i]->key > q->table[i / 2]->key)
swap(q->table, i, i/2);
}
}
static void priority_queue_realloc(PriorityQueue* q) {
q->Capacity *= 2;
q->table = malloc(sizeof(Element*) * q->Capacity);
}
Element* CreateElement(int key, char* value) {
Element* en = malloc(sizeof(*en));
if (en != NULL) {
en->key = key;
en->value = value;
}
return en;
}
int main() {
PriorityQueue* q = priority_queue_initialize(20);
int a[]= { 1, 9, 7, 8, 5, 4, 3, 2, 1, 100, 50, 17 };
for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
{
priority_queue_enqueue(q, a[i],"pq");
}
for (int i = 0; i < q->Size; i++) {
printf("element %d %d %s ,", i,q->table[i]->key, q->table[i]->value);
}
printf("\n");
Element* en = priority_queue_dequeue(q);
printf("%d", en->key);
printf("\n");
for (int i = 0; i < q->Size; i++) {
printf("element %d %d %s ,", i, q->table[i]->key, q->table[i]->value);
}
queue_free(q);
return;
}
3.优先队列题目练习
typedef struct
{
int Capacity;
int Size;
int* table;
}PriorityQueue;
void swapElement(int*table, int i, int j);
PriorityQueue* priority_queue_initialize(int capacity);
void queue_free(PriorityQueue* q);
int priority_queue_top(PriorityQueue* q);
int priority_queue_dequeue(PriorityQueue* q);
void priority_queue_enqueue(PriorityQueue* q, int key);
void priority_queue_adjust(PriorityQueue* q);
int cmp(const void* a, const void* b)
{
int* ptrA = *(int** )a;
int* ptrB = *(int** )b;
if (ptrA[1] == ptrB[1]) {
return (ptrA[0] - ptrB[0]);
}
return (ptrA[1] - ptrB[1]);
}
static void priority_queue_realloc(PriorityQueue* q);
void swapElement(int* table, int i, int j) {
int temp = table[i];
table[i] = table[j];
table[j] = temp;
}
PriorityQueue* priority_queue_initialize(int capacity) {
PriorityQueue* q = malloc(sizeof(*q));
if (q != NULL) {
q->Capacity = capacity;
q->Size = 0;
q->table =malloc(sizeof(int) * q->Capacity);
}
return q;
}
void queue_free(PriorityQueue* q) {
free(q->table);
free(q);
}
int priority_queue_top(PriorityQueue* q) {
if (q->Size > 0)return q->table[0];
return 0;
}
int priority_queue_dequeue(PriorityQueue* q) {
int en=0;
if (q->Size > 0) {
en = q->table[0];
q->table[0] = q->table[q->Size - 1];
q->Size--;
//priority_queue_adjust(q);
}
return en;
}
void priority_queue_enqueue(PriorityQueue* q,int key) {
q->table[q->Size] = key;
q->Size++;
//priority_queue_adjust(q); //入队出队各做一次调整会超时
}
void priority_queue_adjust(PriorityQueue* q) {
for (int i = q->Size - 1; i > 0; i--) {
if (q->table[i] > q->table[i / 2])
swapElement(q->table, i, i/2);
}
}
int scheduleCourse(int** courses, int coursesSize, int* coursesColSize){
qsort(courses, coursesSize, sizeof(courses[0]), cmp);
PriorityQueue*q= priority_queue_initialize(10000);
int time=0;
for(int i=0;i<coursesSize;i++){
if(time+courses[i][0]<=courses[i][1]){
priority_queue_enqueue(q,courses[i][0]);
time+=courses[i][0];
}else{
priority_queue_enqueue(q,courses[i][0]);
priority_queue_adjust(q);
int duration=priority_queue_top(q);
priority_queue_dequeue(q);
time+=courses[i][0]-duration;
}
}
return q->Size;
}
4.两根堆题目:295. 数据流的中位数
一共n个数,如果n是偶数,把这n个数分成大小为n/2的两个堆,分别是大根堆和小根堆,两个堆的堆顶刚好是中位数。
分成两堆怎么分呢?这就需要小顶堆里是较大的一半数,大顶堆里是较小的一半数。也就是,小顶堆的堆顶是较大的n个数里最小的一个。
新加进的数稍微复杂,如果新数比小顶堆的堆顶大,就要加进小顶堆。如果加了之后,小顶堆的大小>大顶堆大小+1,就要将小顶堆的堆顶取出来,放到大顶堆去。
typedef struct {
int size;
int MaxSize;
int MinSize;
int MinHeap[100000];
int MaxHeap[100000];
} MedianFinder;
/** initialize your data structure here. */
void swap(int* ary, int i, int j) {
int temp = ary[i];
ary[i] = ary[j];
ary[j] = temp;
}
void Minswim(int* heap, int size) {
int i = size - 1;
while (i > 1) {
if (heap[i] < heap[i / 2]) { swap(heap, i, i / 2); i = i / 2; }
else break;
}
}
void Minsink(int* heap, int size) {
int i = 1;
while (1) {
int pos = i;
if (i * 2< size && heap[i] > heap[i * 2]) {
pos = i * 2;
}
if (i * 2 + 1 < size && heap[pos] > heap[2 * i + 1])pos = i * 2 + 1;
if (i == pos)break;
swap(heap, i, pos);
i = pos;
}
}
void MinInsert(int* heap, int num, int* size) {
heap[(*size)++] = num;
Minswim(heap, *size);
}
int MinmovTop(int* heap, int size) {
int tmp = heap[1];
heap[1] = heap[--size];
Minsink(heap, size);
return tmp;
}
void Maxswim(int* heap, int size) {
int i = size - 1;
while (i > 1) {
if (heap[i] > heap[i / 2]) { swap(heap, i, i / 2); i = i / 2; }
else break;
}
}
void Maxsink(int* heap, int size) {
int i = 1;
while (1) {
int pos = i;
if (i * 2 < size && heap[i] < heap[i * 2]) {
pos = i * 2;
}
if (i * 2 + 1 < size && heap[pos] < heap[2 * i + 1])pos = i * 2 + 1;
if (i == pos)break;
swap(heap, i, pos);
i = pos;
}
}
int MaxmovTop(int* heap, int size) {
int tmp = heap[1];
heap[1] = heap[--size];
Maxsink(heap, size);
return tmp;
}
void MaxInsert(int* heap, int num, int* size) {
heap[*size] = num;
(*size)++;
Maxswim(heap, *size);
}
MedianFinder* medianFinderCreate() {
MedianFinder* obj = malloc(sizeof(*obj));
obj->size = 0;
obj->MinSize = 1;
obj->MaxSize = 1;
return obj;
}
void medianFinderAddNum(MedianFinder* obj, int num) {
if (obj->size == 0 || num > obj->MinHeap[1]) {
MinInsert(obj->MinHeap, num, &obj->MinSize);
if (obj->MinSize > obj->MaxSize + 1) {
int tmp = MinmovTop(obj->MinHeap, obj->MinSize);
obj->MinSize--;
MaxInsert(obj->MaxHeap, tmp, &obj->MaxSize);
}
}
else {
MaxInsert(obj->MaxHeap, num, &obj->MaxSize);
if (obj->MaxSize > obj->MinSize + 1) {
int tmp = MaxmovTop(obj->MaxHeap, obj->MaxSize);
obj->MaxSize--;
MinInsert(obj->MinHeap, tmp, &obj->MinSize);
}
}
obj->size++;
}
double medianFinderFindMedian(MedianFinder* obj) {
double ret;
if (obj->MaxSize > obj->MinSize)ret = obj->MaxHeap[1];
else if (obj->MaxSize < obj->MinSize)ret = obj->MinHeap[1];
else if (obj->MaxSize == obj->MinSize)ret = (obj->MinHeap[1] + obj->MaxHeap[1]) / 2.0;
return ret;
}
void medianFinderFree(MedianFinder* obj) {
free(obj);
}