1 /*
2 K路归并排序 ,
3 主要思想 :
4 建立K路链表 , 在K路的最小元素提取出来 。
5 存储到 result数组中 , 利用result数组构造最小堆 ,
6 每次取出堆顶的元素 , 在把取出的元素的那路的next填充到堆顶中, 重新维持堆特性
7 通过每次取出堆顶 ,知道K路链表均被取完 ,完成归并排序
8 */
9 #include <stdio.h>
10 #include <algorithm>
11 #include <memory.h>
12
13 using namespace std;
14 //定义链表节点
15 struct node
16 {
17 int data ; //数据
18 node *next;
19 node()
20 {
21 next = NULL;
22 }
23 node( int x )
24 {
25 data = x ;
26 next = NULL;
27 }
28 bool operator<(const node& temp)
29 {
30 if(data < temp.data)
31 return true;
32 return false;
33 }
34 };
35 //定义链表,对于每路定义一个链表,用链表数组lists【101】表示
36 struct list
37 {
38 node *root;
39 node *pre ;
40 list()
41 {
42 root = NULL;
43 }
44 //链表的插入操作
45 void insert( int d )
46 {
47 node* node_temp = new node(d);
48 if(root == NULL)
49
50 {
51 root = node_temp;
52 pre = root ;
53 }
54 else {
55
56 pre->next = node_temp;
57 pre = node_temp;
58 }
59 }
60 }lists[105];
61
62
63
64 int k , n , t ; // k表示归并的路数 , n表示每路所含的数字个数 , t为测试用例个数
65 //定义构造堆的数组result
66 node* result = new node[105];
67 bool cmp( node a , node b)
68 {
69 return ( a.data > b.data );
70 }
71 //保持堆特性函数,非递归写法
72 void min_heapify(node* &a, int i, int length)
73 {
74 int smallest = i;
75 while(smallest <= length - 1)
76 {
77 int left = 2*smallest + 1;
78 int right = 2*smallest + 2;
79 int temp = smallest;
80 if(left <= length - 1 && a[left] < a[smallest])
81 {
82 smallest = left;
83 }
84 if(right <= length - 1 && a[right] < a[smallest])
85 {
86 smallest = right;
87 }
88 //最小的元素位置错误 , 交换其位置 , 使其正确
89 if(smallest != temp)
90 {
91 node exchange = a[smallest];
92 a[smallest] = a[temp];
93 a[temp] = exchange;
94 }
95 else
96 break;
97 }
98 }
99
100 //归并主要函数
101 void merge()
102 {
103 //首先建堆
104 make_heap( result , result + k , cmp );
105
106 while ( k > 0 )
107 {
108 //输出堆顶元素
109 printf("%d " , result[0].data );
110 //判断当前堆顶元素是否存在后续
111 if ( result[0].next != NULL )
112 {
113 //若存在 , 等于后续
114 result[0] = *(result[0].next);
115
116 }
117 else
118 {
119 //若不存在 , 说明该路已完成归并 ,K-- , 并且 将堆的最后一个值赋给堆顶 ,减小堆的节点个数
120 result[0] = result[--k];
121
122 }
123 //保持堆特性
124 min_heapify(result, 0 , k) ;
125 }
126 printf("\n");
127 }
128 int main()
129 {
130 int tep;
131 scanf( "%d" , &t );
132 while ( t -- )
133 {
134 scanf("%d%d" , &k , &n ) ;
135 memset( lists , 0 , sizeof( lists ));
136 for ( int i = 0 ; i < k ; i ++)
137
138 for ( int j = 0 ; j < n ; j++)
139 {
140 scanf("%d" , &tep);
141 lists[i].insert(tep);
142 }
143
144 //构造数组result
145 for ( int i = 0 ; i < k ; i ++)
146 {
147
148 result[i] =* ( lists[i].root );
149 }
150 merge();
151
152 }
153 return 0 ;
154 }