• 寻找最大的K个数(上)


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

      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 }
  • 相关阅读:
    jQuery初学:find()方法及children方法的区别分析
    百万级访问网站前期的技术准备
    TCP/IP协议三次握手与四次握手流程解析
    TCP/IP详解学习笔记
    Dubbo框架入门介绍
    如何提高Web服务端并发效率的异步编程技术
    杂 -- 有关程序员
    关于高性能的那点事
    大型网站的灵魂- 性能
    分布式java应用
  • 原文地址:https://www.cnblogs.com/chuanlong/p/3707282.html
Copyright © 2020-2023  润新知