有关堆存取的习题两例:寻找大富翁、Windows消息队列
2018-01-13 17:26
381 查看
关于堆 (heap) 的笔记见 -> 有关堆 (数据结构) 的笔记
“寻找大富翁”的题面是这样:
2015年胡润研究院的调查显示,截至2014年9月,个人资产在600万元以上高净值人群达290万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。
输入格式:
输入首先给出两个正整数N(≤10^6)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。
输出格式:
在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。
输入样例:
8 3
8 12 7 3 20 9 5 18
输出样例:
20 18 12
“从若干数里找最大的x个数”这类的题目可以通过建立堆解出,下面是解法。
“Windows消息队列”的题面如下:
4000
消息队列是Windows系统的基础。对于每个进程,系统维护一个消息队列。如果在进程中有特定事件发生,如点击鼠标、文字改变等,系统将把这个消息加到队列当中。同时,如果队列不是空的,这一进程循环地从队列中按照优先级获取消息。请注意优先级值低意味着优先级高。
请编辑程序模拟消息队列,将消息加到队列中以及从队列中获取消息。
输入格式:
输入首先给出正整数N(≤10^5),随后N行,每行给出一个指令——GET或PUT,分别表示从队列中取出消息或将消息添加到队列中。 如果指令是PUT,后面就有一个消息名称、以及一个正整数表示消息的优先级,此数越小表示优先级越高。
消息名称是长度不超过10个字符且不含空格的字符串;题目保证队列中消息的优先级无重复,且输入至少有一个GET。
输出格式:
对于每个GET指令,在一行中输出消息队列中优先级最高的消息的名称和参数。如果消息队列中没有消息,输出EMPTY
QUEUE!。对于PUT指令则没有输出。
输入样例:
9
PUT msg1 5
PUT msg2 4
GET
PUT msg3 2
PUT msg4 4
GET
GET
GET
输出样例:
msg2
msg3
msg4
msg1
EMPTY QUEUE!
因为要靠结构体内的成员作为标签定义大小关系,会稍微有些麻烦。但涉及到频繁存取数据的场合使用堆依然是合适的。
“寻找大富翁”的题面是这样:
2015年胡润研究院的调查显示,截至2014年9月,个人资产在600万元以上高净值人群达290万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。
输入格式:
输入首先给出两个正整数N(≤10^6)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。
输出格式:
在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。
输入样例:
8 3
8 12 7 3 20 9 5 18
输出样例:
20 18 12
“从若干数里找最大的x个数”这类的题目可以通过建立堆解出,下面是解法。
#include<stdio.h> #include<stdlib.h> #define MINVAL -1 #define EMPTY -404 struct node { int* body; int size; int capacity; }; typedef struct node* Heap; //这个命名可能是迷惑性的,因为我也用这个结构体建了一个栈 Heap NewHeap(int size); void DelKit(Heap heap); int EnHeap(Heap heap, int tmp); int PopHeap(Heap heap); int EnStack(Heap stack, int tmp); int PopStack(Heap stack); int main(void) { int N, M; scanf("%d %d", &N, &M); getchar(); Heap H = NewHeap(M); Heap stack = NewHeap(M); int i, tmp; for(i = 0; i < N; i++) { scanf("%d", &tmp); getchar(); while(EnHeap(H, tmp)) PopHeap(H); } int sizeH = H->size; for(i = 0; i < sizeH; i++) { tmp = PopHeap(H); EnStack(stack, tmp); } i = 0; while(stack->size) { tmp = PopStack(stack); if(i != 0) putchar(' '); printf("%d", tmp); i++; } DelKit(H); DelKit(stack); return 0; } Heap NewHeap(int size) { Heap heap = (Heap)calloc(1, sizeof(struct node)); heap->body = (int*)calloc(size+1, sizeof(int)); heap->body[0] = MINVAL; heap->size = 0; heap->capacity = size; return heap; } void DelKit(Heap heap) { free(heap->body); heap->body = NULL; free(heap); heap = NULL; return; } //插入数据到小顶堆 int EnHeap(Heap heap, int tmp) { int x; if(heap->size == heap->capacity) { return 1; } x = ++heap->size; for(; heap->body[x>>1]>tmp && x>0; x>>=1) //循环限定 x>=1, 可以不使用哨兵(body[0]) heap->body[x] = heap->body[x>>1]; heap->body[x] = tmp; return 0; } //从小顶堆弹出 int PopHeap(Heap heap) { int Parent, Child; int minData, x; if(heap->size == 0) { return EMPTY; } minData = heap->body[1]; x = heap->body[heap->size--]; for(Parent = 1; Parent<<1 <= heap->size; Parent = Child) { Child = Parent<<1; if( (Child < heap->size) && (heap->body[Child] > heap->body[Child+1]) ) Child++; if(x <= heap->body[Child]) break; else heap->body[Parent] = heap->body[Child]; } heap->body[Parent] = x; return minData; } //进栈 int EnStack(Heap stack, int tmp) { if(stack->size == stack->capacity) { return 1; } stack->body[stack->size++] = tmp; return 0; } //出栈 int PopStack(Heap stack) { if(stack->size == 0) { return EMPTY; } stack->size--; return stack->body[stack->size]; }
“Windows消息队列”的题面如下:
4000
消息队列是Windows系统的基础。对于每个进程,系统维护一个消息队列。如果在进程中有特定事件发生,如点击鼠标、文字改变等,系统将把这个消息加到队列当中。同时,如果队列不是空的,这一进程循环地从队列中按照优先级获取消息。请注意优先级值低意味着优先级高。
请编辑程序模拟消息队列,将消息加到队列中以及从队列中获取消息。
输入格式:
输入首先给出正整数N(≤10^5),随后N行,每行给出一个指令——GET或PUT,分别表示从队列中取出消息或将消息添加到队列中。 如果指令是PUT,后面就有一个消息名称、以及一个正整数表示消息的优先级,此数越小表示优先级越高。
消息名称是长度不超过10个字符且不含空格的字符串;题目保证队列中消息的优先级无重复,且输入至少有一个GET。
输出格式:
对于每个GET指令,在一行中输出消息队列中优先级最高的消息的名称和参数。如果消息队列中没有消息,输出EMPTY
QUEUE!。对于PUT指令则没有输出。
输入样例:
9
PUT msg1 5
PUT msg2 4
GET
PUT msg3 2
PUT msg4 4
GET
GET
GET
输出样例:
msg2
msg3
msg4
msg1
EMPTY QUEUE!
因为要靠结构体内的成员作为标签定义大小关系,会稍微有些麻烦。但涉及到频繁存取数据的场合使用堆依然是合适的。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<stdbool.h> #define MINDATA -1 typedef char wMSG[11]; struct worder { wMSG msg; int rank; }; typedef struct worder* ordTbl; struct orderHeap { ordTbl body; int heapSize; int Capacity; }; typedef struct orderHeap* Ord; Ord OrderTable(int); void DelOrderTable(Ord); bool EnOrderTable(Ord, wMSG, int); void GetOrderTable(Ord); int main() { int size; scanf("%d", &size); getchar(); Ord msgQue = OrderTable(size+1); char ord[4]; wMSG msgTmp; int i, rankTmp; for(i=0; i<size; i++) { scanf("%s", &ord); getchar(); if(ord[0] == 'P') //Put in { scanf("%s %d", &msgTmp, &rankTmp); getchar(); EnOrderTable(msgQue, msgTmp, rankTmp); } else //Get { GetOrderTable(msgQue); } } DelOrderTable(msgQue); return 0; } Ord OrderTable(int size) { Ord WOrd = (Ord)calloc(1,sizeof(struct orderHeap)); WOrd->body = (ordTbl)calloc(size, sizeof(struct worder)); WOrd->Capacity = size; WOrd->heapSize = 0; WOrd->body[0].rank = MINDATA; return WOrd; } void DelOrderTable(Ord WOrd) { free(WOrd->body); WOrd->body = NULL; free(WOrd); WOrd = NULL; return; } //向堆中写入新节点, r 是 rank bool EnOrderTable(Ord WOrd, wMSG ch, int r) { if(WOrd->heapSize == WOrd->Capacity) { return false; } int i = ++WOrd->heapSize; for(; WOrd->body[i>>1].rank > r; i>>=1) WOrd->body[i] = WOrd->body[i>>1]; WOrd->body[i].rank = r; strcpy(WOrd->body[i].msg, ch); return true; } void GetOrderTable(Ord WOrd) { if(WOrd->heapSize == 0) { printf("EMPTY QUEUE!\n"); return; } int Parent, Child; ordTbl tempNode; //堆顶元素在下滤后会被覆盖,在这之前显示信息 printf("%s\n", WOrd->body[1].msg); //下滤节点在调整前的堆区域外,可直接取地址 tempNode = &WOrd->body[WOrd->heapSize--]; for(Parent = 1; Parent<<1 <= WOrd->heapSize; Parent = Child) { Child = Parent<<1; if( (Child != WOrd->heapSize) && (WOrd->body[Child].rank > WOrd->body[Child+1].rank) ) Child++; if( tempNode->rank <= WOrd->body[Child].rank ) break; else WOrd->body[Parent] = WOrd->body[Child]; //下滤 } WOrd->body[Parent] = *tempNode; //下滤后将节点放入 return; }
相关文章推荐
- windows消息和消息队列
- windows消息和消息队列 二
- windows程序消息机制(Winform界面更新有关)
- HDU1509-优先队列-Windows消息队列
- 在IBM WebSphere MQ本地队列中存取消息
- 详谈UI线程和Windows消息队列
- 细说UI线程和Windows消息队列
- 5-26 Windows消息队列
- Windows是不是每个线程都有消息队列的问题
- 消息队列有关的数据结构
- zoj 2724 Windows Message Queue(使用priority_queue容器模拟消息队列)
- 天梯赛训练 Windows消息队列(25 分)
- Windows消息队列,UI线程,窗口以及消息处理方式总结
- Windows消息机制之二(续)-- windows消息和消息队列
- 细说UI线程和Windows消息队列
- 在 Windows 7 上安装消息队列
- 关于Windows消息队列的几个问题
- 细说UI线程和Windows消息队列
- windows 消息队列,消息循环,模态对话框
- windows消息队列