数据结构与算法分析——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
#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); }
#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); }