这是一道很经典的题目,有太多方法了,今天写了两种方法,分别是快排和堆排序

  1 #include <iostream>
  2 using namespace std;
  3 #define N 25
  4 
  5 //初始化数组
  6 //int a[] = {6, 2, 3, 9, 4, 3, 1, 2, 4, 4};
  7 //int a[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
  8 int a[] = {1, 2, 3, 4, 5, 6};
  9 int n = 6;
 10 int K = 3;
 11 
 12 //快速排序,o(nlogn),最应该想到的思路,排好序要多大数就输出多大数
 13 /*
 14     partition就是挖第一个洞,从后往前找,找到,挖起来,把前面的洞埋上,再从前往后找,找到,挖起来,把后面的洞埋上,直到最后,high=low了,把这个洞补上
 15 */
 16 int partition(int* p, int low, int high)
 17 {
 18     int i;
 19     int pivot;
 20     //把第一个数拿出来,挖个洞
 21     pivot = p[low];
 22     while (low < high)
 23     {
 24         //从后往前找,找到比pivot小的值
 25         while (low < high && p[high] >= pivot)
 26             high--;
 27         //然后后面的数埋上前面的洞
 28         //Note这里无须再加个if,因为即使相同了,那我再做一步也无妨,而且也无须把low指针往上移,因为,到时候我可以再判断一次,还是可以移动的
 29         p[low] = p[high];
 30         
 31         //从前往后找,找到比pivot大的值,然后把前面的数埋上
 32         while (low < high && p[low] <= pivot)
 33             low++;
 34         p[high] = p[low];
 35     }
 36     //这里low和high已经相同了,所以也可以写成p[high]=pivot,这一步就是把洞埋上
 37     p[low] = pivot;
 38     return low;
 39 }
 40 /*
 41     其实,两个可以写一起,但是,分开写更清楚
 42     quickSort函数就是当low<high时,进行一次partition,然后再对分开的两块进行quickSort
 43 */
 44 void quickSort(int* p, int low, int high)
 45 {
 46     if(low < high)
 47     {
 48         int breakpoint = partition(p, low, high);
 49         quickSort(p, low, breakpoint - 1);
 50         quickSort(p, breakpoint + 1, high);
 51     }
 52 }
 53 
 54 //堆排序, o(nlogk),考虑到只需取K大的数,那就无须对n个数都排序,只需记录下k个即可
 55 int heap[N];
 56 /*
 57     //这里有点疑问哦,考虑到heap数组可能比较大,所以想定义成全局变量,可是这样就不必传递参数勒,定义成局部变量,参数又太多
 58     目前定义成全局变量
 59     input: lastIndex指heap数组要插入的value的位置(是要插入的位置哦); value指要插入的数字
 60     function: heap数组是从index=0开始储存的,就是把value储存heap数组内,并进行相应的调整,符合最大堆的性质
 61 */
 62 void MaxHeapPush(int lastIndex, int value)
 63 {
 64     //把value放在堆的末尾
 65     heap[lastIndex] = value;
 66     //记录下末尾的index
 67     int index = lastIndex;
 68     // 不断向上调整
 69     while (index)
 70     {
 71         //若比上面的大,就交换
 72         if (heap[index] > heap[(index - 1) / 2])
 73         {
 74             int temp = heap[index];
 75             heap[index] = heap[(index - 1) / 2];
 76             heap[(index - 1) / 2] = temp;
 77         }
 78         //否则,说明已经调整好了,立即停止
 79         else
 80             break;
 81         //若没有break出来,就要一直调整了,所以index要变动
 82         index = (index - 1) / 2;
 83     }
 84 }
 85 /*
 86     input:
 87         p数组要初始化数组,提供数据的
 88         n表示该数组的长度,c就是麻烦,连长度都要传入
 89         heapSize表示要维护的堆的大小,Note,一定要大于K哦
 90 */
 91 void MaxHeapInit(int *p, int n, int heapSize)
 92 {
 93     int i, lastIndex;
 94     lastIndex = 0;
 95     for (i = 0; i < n; i++)
 96     {
 97         //依次插入
 98         MaxHeapPush(lastIndex, p[i]);
 99         // 若比预定好的堆的大小小的话,最后一个value的值就要增加了
100         if (lastIndex < heapSize)
101             lastIndex++;
102     }
103 }
104 
105 /*
106     input: lastIndex是要删除的value的位置(这里千万要注意,其实,跟前面的lastIndex有点不一样)
107 */
108 int MaxHeapPop(int lastIndex)
109 {
110     // 交换头尾value
111     int temp, i;
112     temp = heap[0];
113     heap[0] = heap[lastIndex];
114     heap[lastIndex] = temp;
115     // 向下调整
116     i = 0;
117     int child = 2 * i + 1;
118     while (child < lastIndex)
119     {
120         //若有右孩子节点,且右节点比左节点大,那要只需要比较右节点即可
121         if (child + 1 < lastIndex && heap[2 * i + 2] > heap[2 * i + 1])
122         {
123             child = child + 1;
124         }
125         //若孩子节点比父节点大,两个节点交换
126         if (heap[child] > heap[i])
127         {
128             temp = heap[child];
129             heap[child] = heap[i];
130             heap[i] = temp;
131         }
132         //否则说明已经有序,停止
133         else
134             break;
135         // 变化孩子节点的index
136         child = 2 * i + 1;
137     }
138     // 返回末尾value
139     return heap[lastIndex];
140 }
141 
142 int main()
143 {
144     int i, j;
145     for (i = 0; i < n; i++)
146         cout<<a[i]<<" ";
147     cout<<endl;
148     /*
149     //快排,若取前K大的数,只需从末尾到前输出K个数即可
150     quickSort(a, 0, n - 1);
151     for (i = 0; i < n; i++)
152         cout<<a[i]<<" ";
153     cout<<endl;
154     */
155     
156     //注意这里之所以乘以2,是因为只维护K个数字的堆,不能得到前K个大的数!!
157     MaxHeapInit(a, n, K * 2 - 1);
158     for (i = 0; i < n; i++)
159         cout<<heap[i]<<" ";
160     cout<<endl;
161 
162     // 输出,这里的lastIndex是变化的哦,因为之前维护的2 * K - 1的堆,所以这里也应该是2 * K - 1
163     for (i = 0; i < K; i++)
164         cout<<MaxHeapPop(2 * K - 1 - i)<<" ";
165     cout<<endl;
166     
167     system("pause");
168     return 0;
169 }

 

posted on 2014-05-04 16:09  MrMission  阅读(531)  评论(0编辑  收藏  举报