【算法学习笔记】21.算法设计初步 求第k个数 划分法 快排法
来源:互联网 发布:sql 修改自增列的值 编辑:程序博客网 时间:2024/05/06 08:37
第一种方法, 主要是分组每组五个排序,取中位数,再取中位数的中位数然后进行分割,根据MoM和k的比较进行递归查找。
但是貌似当数量一大的时候,容易出现问题。暂时留有一定的疑问。这个的复杂度也是O(n)。
//选择排序void SelectSort(long* A,int len=5){ for (int i=0; i<len; i++) { for (int j=i+1; j<len; j++) { if(A[i]>A[j]){ long t=A[i]; A[i]=A[j]; A[j]=t; } } }}//划分A 长度是len 把A分成比x大的和和比x小的两部分int Partition(long *A,int len,long x){ //初始化三个数组 //left是比x小的 right是比x大的 middle是和x一样的 long left[Max_N],right[Max_N],middle[Max_N]; int left_len=0,right_len=0,middle_len=0; //循环的去看A中各个元素 然后放在不同的数组里 for (int k=1; k<=len; k++) { if(A[k-1]<x) left[left_len++]=A[k-1]; else if(A[k-1]>x) right[right_len++]=A[k-1]; else middle[middle_len++]=A[k-1]; } //cur是光标 把三个数组按顺序放回A中 int cur=0; for (; cur<left_len; cur++) A[cur]=left[cur]; A[cur] = x; for (int j=0; j<middle_len; j++) A[cur+j]=middle[j]; for (int j=0; j<right_len; j++) A[cur+j]=right[j]; //返回第一个x的下标 return left_len+1;}long Select(long* A,int len,int i){ if (len<=5) { //每组分成5个 如果小于5 直接返回 SelectSort(A,len); return A[i-1]; } for (int j=1; j<=len/5; j++) { SelectSort(A+(j-1)*5,5);//每小组进行排序 //交换 A[j-1]和A[(j-1)*5+3] 要把所有的中位数前移!为了取中位数的中位数MoM //不用考虑剩余的没有进行分组中的元素 因为他们都在划分中考虑了 long t=A[(j-1)*5+2];//t是5个数中的中位数 A[(j-1)*5+2]=A[j-1]; A[j-1]=t; } //取MoM 中位数的中位数 long MoM = Select(A, len/5, (len/10==0)?1:len/10); //k是划分成两半之后MoM所在的位置 int k = Partition(A, len, MoM); long t=0; if (k==i) //如果k正好是要找的那个元素 就直接返回MoM t = MoM; //在两半中继续找 else if(k>i) t = Select(A, k-1, i); else t = Select(A+k-1, len-k, i-k); return t;}
第二种方法 利用快速排序
先简单说一下快速排序的思想。
从核心思想上来说,快速排序和归并排序很像,只是归并排序的两边并不是有序的,所以最后要进行合并,而快速排序则不是。
1.划分问题:把数组的各个元素重排后分成两部分,使左边的每个元素都小于右边的元素。
2.递归求解:左右分别排序
3.合并问题:不用合并,因为此时数组已经拍完序。
划分的过程有多种多样。
第k个数正好就是可以判断k 分别每次都进行选择在左边或者右边进行查找。
快速排序(Quicksort)是对冒泡排序的一种改进。
最简单易懂的版本。
void QckSort(int* A,int low,int high){ //low是所需排的最低下标 hight是所需排的最高下标 if(high<=low) return; int i=low,j=high; int key = A[i];//随便找个key 方便起见取第一个 留出回旋的空间 while (i<j) {//两个机器人还没有相遇的时候 //右边的j机器人向左走 遇到比key小的就扔给i机器人 while (i<j && A[j]>=key) j--; //开始扔 A[i] = A[j]; //左边的i机器人向右走 遇到比key大的石头就扔给j机器人 while (i<j && A[i]<=key) i++; //开始扔 A[j] = A[i]; } A[i]=key;//此时两个机器人已经相遇了,所以是i==j //因为此时i是key 不用考虑 QckSort(A, low, i-1);//注意是[low,i-1] QckSort(A, i+1, high);//是[i+1,high] return;}
于是找第k个数就变成了这样
//找第k个数int QckFind(int* A,int low,int high,int k){ //low是所需排的最低下标 hight是所需排的最高下标 if(high<=low) return A[low]; int i=low,j=high; int key = A[i];//随便找个key 方便起见取第一个 留出回旋的空间 while (i<j) {//两个机器人还没有相遇的时候 //右边的j机器人向左走 遇到比key小的就扔给i机器人 while (i<j && A[j]>=key) j--; //开始扔 A[i] = A[j]; //左边的i机器人向右走 遇到比key大的石头就扔给j机器人 while (i<j && A[i]<=key) i++; //开始扔 A[j] = A[i]; } A[i]=key;//此时两个机器人已经相遇了,所以是i==j //因为此时i是key 不用考虑 if(i==(k-1)) return key; if(i<(k-1)) return QckFind(A,low,i-1,k); else return QckFind(A,i+1,high,k-1-i);}
0 0
- 【算法学习笔记】21.算法设计初步 求第k个数 划分法 快排法
- 快排划分算法求k个数小于某数
- 【算法学习笔记】20.算法设计初步 归并排序 求逆序数
- 求集合所有K划分的算法
- BFPTR算法(中位数的中位数算法)求n个数中第k大的数
- bfprt算法求最小的k个数
- 算法:求由2的k次方*3的k次方*5的k次方得到的第k个数
- 【数据结构与算法】:倒数第K个数
- 007-寻找第k小元素-分治法-《算法设计技巧与分析》M.H.A学习笔记
- 分治算法求N个数中第K小(大)的数
- BFPRT算法求第k大数
- 算法求第K小元素思路
- 【算法】求第k大的数
- 设计算法,找到质因数只有3,5或7的第k个数。
- 第k元素log(n)算法--划分树
- SOJ-3010(划分树求区间内的第k个数)
- 设计一个算法,求非空二叉树中指定的第k层(k>1)的叶子节点的个数
- 算法之求数组中最小的K个数
- InfoPath与SharePoint之(六)在表单库里引用InfoPath Form Content Type
- 界面选择-----做前台的一些积累
- Wireshark基本介绍和学习TCP三次握手
- The kth great number(第k大数模板题:优先队列或树状数组或SBT)
- alter table table_name enable row movement
- 【算法学习笔记】21.算法设计初步 求第k个数 划分法 快排法
- C++ STL 算法:transform
- 成绩管理项目现阶段总结
- maven 快速参考手册
- 云风的 blog 上关于 skynet 的分类
- MQ-MessageQueue 消息队列
- SIP消息头域
- 【Linus】CentOS下设置快捷键
- 带你一起Piu Piu Piu