优先队列的应用 选择问题

数据结构与算法分析——c语言描述 第六章


昨天参加个学校的编程大赛,被信电院和其他院的大一吊打。只有更努力才能看见别人的背影。


6A,复杂度是O(N+klogN)

main.c

#include"binheap.h"
#include<stdlib.h>
#include<stdio.h>

int RandInt(int i, int j) {
	int temp;
	temp = (int)(i + (1.0*rand() / RAND_MAX)*(j - i));
	return temp;
}

void getRandomInt(int *A, int n) {
	for (int i = 0; i < n; i++) {
		A[i] = i + 1;
	}

	for (int i = 1; i < n; i++) {
		//std::swap(A[i], A[RandInt(0, i)]);  
		int randAdrr = RandInt(0, i);
		int t = A[i];
		A[i] = A[randAdrr];
		A[randAdrr] = t;
	}
}

int main() {
	int n, k;
	scanf("%d%d", &n, &k);
	PriorityQueue h = initialize(n);
	int *a = malloc(sizeof(int)*n);
	getRandomInt(a, n);

	for (int i = 0; i < n; i++) {
		insert(a[i], h);
	}
	for (int i = 0; i < k-1; i++) {
		deleteMin(h);
	}
	printf("%d", deleteMin(h));
	destroy(h);
	free(a);
	
}


6B

binheap.h

#ifndef _BinHeap_H

typedef int ElementType;

struct HeapStruct;
typedef struct HeapStruct *PriorityQueue;

PriorityQueue initialize(int maxElements);
PriorityQueue buildHeap(ElementType *arr,int n, int maxElements);
void destroy(PriorityQueue h);
void makeEmpty(PriorityQueue h);
void insert(ElementType X, PriorityQueue h);
ElementType deleteMin(PriorityQueue h);
int isEmpty(PriorityQueue h);
int isFull(PriorityQueue h);
ElementType getMin(PriorityQueue h);
void decreaseKey(int pos, ElementType delta,PriorityQueue h);
void increaseKey(int pos, ElementType delta, PriorityQueue h);
void Delete(int pos, PriorityQueue h);
#endif // !_BinHeap_H

binheap.c

#include"binheap.h"
#include"fatal.h"

#define MinPQSize 5
#define MinData INT_MIN

struct HeapStruct {
	int capacity;
	int size;
	ElementType* elements;
};

PriorityQueue initialize(int maxElements) {
	PriorityQueue h;
	if (maxElements < MinPQSize)
		Error("Priority queue size is too small");
	h = malloc(sizeof(struct HeapStruct));
	if (h == NULL)
		Error("OUT OF MEMORY");
	h->elements = malloc(sizeof(ElementType)*(maxElements + 1));//多出来的一个用于存放最小的元素,其用来和堆顶比较
	if (h->elements == NULL)
		Error("OUT OF MEMORY");
	h->capacity = maxElements;
	h->size = 0;
	h->elements[0] = MinData;
	return h;
}

static void percolateDown(int pos, PriorityQueue h) {
	ElementType elem = h->elements[pos];
	int i, child;
	for (i = pos; i < h->size; i = child) {
		child = i * 2;

		if (child > h->size)
			break;

		if (child != h->size &&h->elements[child] > h->elements[child + 1])
			child++;
		if (elem > h->elements[child])
			h->elements[i] = h->elements[child];
		else
			break;
	}
	h->elements[i] = elem;
}

PriorityQueue buildHeap(ElementType *arr, int n, int maxElements) {
	PriorityQueue h = initialize(maxElements);
	
	h->size = n;
	for (int i = 0; i < n; i++) {
		h->elements[i + 1] = arr[i];
	}
	
	for (int i = n / 2; i > 0; i--) {
		percolateDown(i, h);
	}
	
	return h;
}

void destroy(PriorityQueue h) {
	free(h->elements);
	free(h);
}

void makeEmpty(PriorityQueue h) {
	h->size = 0;
}

void insert(ElementType X, PriorityQueue h) {
	int i;
	if (isFull(h))
		Error("priority queue is full");
	for (i = (++h->size); h->elements[i / 2] > X; i /= 2)//前缀++是因为真正有用的从1开始。判断父亲是不是X大,堆顶肯定停下来,MINDATA的缘故
		h->elements[i] = h->elements[i / 2];
	h->elements[i] = X;
}

ElementType deleteMin(PriorityQueue h) {//
	int i, child;
	ElementType minElement, lastElement;
	if (isEmpty(h))
		Error("priority queue is empty");
	minElement = h->elements[1];
	lastElement = h->elements[h->size--];//删除右下的元素
	for (i = 1; i <= h->size; i = child) {
		child = i * 2;
		if (child > h->size)//这个用于在最底层的时候,获得的儿子是越界的,此时i是上一次迭代的child,child两儿子中的最小值
			break;
		if (child < h->size && h->elements[child] > h->elements[child + 1]) {//不一定有两个儿子
			child++;
		}
		if (lastElement > h->elements[child])
			h->elements[i] = h->elements[child];
		else
			break;
	}

	h->elements[i] = lastElement;
	return minElement;
}

int isEmpty(PriorityQueue h) {
	return h->size == 0;
}

int isFull(PriorityQueue h) {
	return h->size == h->capacity;
}

ElementType getMin(PriorityQueue h) {
	if (isEmpty(h))
		Error("EMPTY HEAP");
	return h->elements[1];
}

void decreaseKey(int pos, ElementType delta, PriorityQueue h) {
	if (pos<1 || pos>h->size)
		Error("Positon Error");
	ElementType changedElem = h->elements[pos] - delta;
	int i;
	for (i = pos; h->elements[i / 2] > changedElem; i /= 2) {
		h->elements[i] = h->elements[i / 2];
	}
	h->elements[i] = changedElem;
}

void increaseKey(int pos, ElementType delta, PriorityQueue h) {
	if (pos<1 || pos>h->size)
		Error("Positon Error");
	ElementType changedElem = h->elements[pos] + delta;
	int i, child;
	for (i = pos; i < h->size; i = child) {
		child = i * 2;
		if (child > h->size)
			break;
		if (child != h->size&&h->elements[child] > h->elements[child + 1])
			child++;
		if (changedElem > h->elements[child])
			h->elements[i] = h->elements[child];
		else
			break;
	}
	h->elements[i] = changedElem;
}

void Delete(int pos, PriorityQueue h) {
	if (pos<1 || pos>h->size)
		Error("Positon Error");
	for (int i = pos; i > 1; i /= 2) {
		h->elements[i] = h->elements[i / 2];
	}
	deleteMin(h);
}

main.c

#include"binheap.h"
#include<stdlib.h>
#include<stdio.h>

int RandInt(int i, int j) {
	int temp;
	temp = (int)(i + (1.0*rand() / RAND_MAX)*(j - i));
	return temp;
}

void getRandomInt(int *A, int n) {
	for (int i = 0; i < n; i++) {
		A[i] = i + 1;
	}

	for (int i = 1; i < n; i++) {
		//std::swap(A[i], A[RandInt(0, i)]);  
		int randAdrr = RandInt(0, i);
		int t = A[i];
		A[i] = A[randAdrr];
		A[randAdrr] = t;
	}
}

int a[99999999];

int main() {
	int n, k;
	scanf("%d%d", &n, &k);
	//int *a = malloc(sizeof(int)*n);
	//if (a == NULL)
	//	fprintf(stderr,"out of memory");
	getRandomInt(a, n);

	PriorityQueue h= buildHeap(a, k, n);//O(k)

	for (int i = k; i < n; i++) {//O((n-k)*logk)
		if (a[i] > getMin(h)) {
			deleteMin(h);
			insert(a[i], h);
		}
	}
	printf("%d", getMin(h));
	destroy(h);
	//free(a);
	
}


你可能感兴趣的:(优先队列的应用 选择问题)