堆排序和优先队列(215. 数组中的第K个最大元素,630. 课程表 III)

目录

1. 堆排序

 2. 优先队列

3.优先队列题目练习 

4.两根堆题目:295. 数据流的中位数


1. 堆排序

215. 数组中的第K个最大元素

      创建一个大小为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.优先队列题目练习 

630. 课程表 III

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. 数据流的中位数

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);
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值