在公司面试时,当场写排序比较多,虽然都是老掉牙的问题,还是要好好准备下

快速排序,以第一个元素为关键词比较,每次比较结束,关键词都会去到最终位置上

//7 3 2 9 8 3 4 6
//7 3 2 9 8 5 4 6
//7 5 2 9 8 3 4 6 #include<stdio.h>
int s[];
void mysort(int left,int right){
if(left>=right)return; int mid,key=s[left];
int ll=left,rr=right;
while(ll<rr){
while(s[rr]>=key&&ll<rr)rr--;
s[ll]=s[rr];
while(s[ll]<=key&&ll<rr)ll++;
s[rr]=s[ll];
}s[ll]=key;
mysort(left,ll-);
mysort(ll+,right);
} int main(){
int n;
while(scanf("%d",&n)!=EOF){
int i,k;
for(i=;i<=n;i++){
scanf("%d",&s[i]);
} mysort(,n);
for(i=;i<=n;i++){
printf("%d\n",s[i]);
}
} return ;
}

改了下,更通俗了些

#include<stdio.h>
#include<time.h>
#include<iostream>
using namespace std; int shu[]={,,,,,,,,,}; void quickSort(int left,int right){
if(left>=right) return ;
int ll=left,rr=right;
int temp=shu[left];
while(ll<rr){
while(temp<=shu[rr]&&rr>left)rr--;
while(temp>=shu[ll]&&ll<right)ll++;
if(ll>=rr)break;
swap(shu[ll],shu[rr]);
}
swap(shu[left],shu[rr]);
quickSort(left,rr);
quickSort(rr+,right);
} int main(){
int i,n=;
for(i=;i<=n;i++){
shu[i]=rand()%;
printf("%d ",shu[i]);
}
quickSort(,n); for(i=;i<=n;i++){
printf("%d ",shu[i]);
}
getchar();
}

第k大的元素,其实就是在快速排序的基础上对递归做了个限制,就是对一边进行递归, 比如Kth的位置在key的左边,我们就递归(left,ll-1);反之(ll+1,right)

//7 3 2 9 8 3 4 6    1
//7 3 2 9 8 3 4 6 2
//7 3 2 9 8 3 4 6 3
//7 3 2 9 8 3 4 6 4
//7 3 2 9 8 3 4 6 7 #include<stdio.h>
int s[]; int findKth=,kth;
void kth_element(int left,int right){
if(left>=right)return;
if(findKth==){
return ;
} int mid,key=s[left];
int ll=left,rr=right;
while(ll<rr){
while(s[rr]>=key&&ll<rr)rr--;
s[ll]=s[rr];
while(s[ll]<=key&&ll<rr)ll++;
s[rr]=s[ll];
}s[ll]=key;
if(kth<ll)
kth_element(left,ll-);
else if(kth>ll)
kth_element(ll+,right);
else{
findKth=;
return ;
}
} int main(){
int n;
while(scanf("%d",&n)!=EOF){
int i,k;
for(i=;i<=n;i++){
scanf("%d",&s[i]);
}
scanf("%d",&kth);
findKth=;
kth_element(,n);
printf("%d\n",s[kth]); //mysort(1,n);
for(i=;i<=n;i++){
printf("%d ",s[i]);
}printf("\n");
} return ;
}

改的适合自己的模板

#include<stdio.h>
#include<time.h>
#include<iostream>
using namespace std; int shu[]={,,,,,,,,,};
int key,ret;
int ok; void Kth(int left,int right){
if(ok==)return;
if(left>=right) return ;
int ll=left,rr=right;
int temp=shu[left];
while(ll<rr){
while(temp<=shu[rr]&&rr>left)rr--;
while(temp>=shu[ll]&&ll<right)ll++;
if(ll>=rr)break;
swap(shu[ll],shu[rr]);
}
swap(shu[left],shu[rr]);
if(rr==key){
ok=;
ret=shu[rr];
return ;
} if(key<rr)
Kth(left,rr);
else
Kth(rr+,right);
} int main(){
int i,n=;
srand(time(NULL));
for(i=;i<=n;i++){
shu[i]=rand()%;
printf("%d ",shu[i]);
}printf("\n"); key=;
ok=;
Kth(,n); for(i=;i<=n;i++){
printf("%d ",shu[i]);
}printf("\n");
printf("kth = %d\n",ret);
getchar();
}

根据堆的定义,堆是一个完全二叉树,手写了个大顶堆,其实堆就两个操作,入堆(需要向上调整),出堆(需要向下调整),堆排序就是依次把堆顶元素出堆

向上调整不需要选择,因为祖先只有一个;向下调整需要选择是从左子树还是右子树,因为儿子可能有两个

#include<iostream>
#include<cstdio>
#include<time.h>
using namespace std;
double test[],s[]; int head_size;
void head_push(int k,double temp){//入堆其实是一个向上调整的过程
int n=k;
s[k]=temp;
while(n!=){
if(s[n/]<s[n]){
swap(s[n/],s[n]);
}
n=n/;
}
return ;
} void head_pop(){//堆顶元素出堆其实是向下调整的过程
int n=;
s[]=s[head_size+];
while(n*<=head_size){
if(n*+<=head_size){//右儿子存在
if(s[n]>=s[*n+]&&s[n]>=s[*n])break;//父节点比两个儿子都大退出
if(s[*n+]>s[*n]){ //右儿子比左儿子大
swap(s[n],s[*n+]);
n=n*+;
}else{ //左儿子比右儿子大
swap(s[n],s[*n]);
n=n*;
}
}
else{//只存在左儿子
if(s[n]>=s[*n])break;//父节点比左儿子大退出
swap(s[n],s[*n]);
n=n*;
}
}
return;
} void headSort(double *input,int left,int right){
int i;
head_size=;
for(i=left;i<=right;i++){
head_size++;
head_push(head_size,input[i]);
} for(i=left;i<=right;i++){
input[i]=s[];
head_size--;
head_pop();
} int half=(left+right)>>;
double temp;
for(i=left;i<=half;i++){//因为是大顶堆,所以要调整
temp=input[i];input[i]=input[right-i+];input[right-i+]=temp;
} } int main(){
freopen(" data.txt","r",stdin);
time(NULL);
int i; for(i=;i<=;i++){
scanf("%lf",&test[i]);
}
headSort(test,,); printf("第1个:%lf\n",test[]);
printf("第10个:%lf\n",test[]);
printf("第100个:%lf\n",test[]);
printf("第1000个:%lf\n",test[]);
printf("第10000个:%lf\n",test[]); return ;
}

//发现原来的堆排序写的有点罗嗦,改了一下

#include<iostream>
#include<stdio.h>
using namespace std; int head_size;
int s[]={,,,,,,,,,};
int temp[]; //大顶堆
void shiftUp(int a[],int i){
while(i>&&a[i]>a[i/]){
swap(a[i],a[i/]);
i>>=;
}
} void shiftDown(int a[],int i,int n){
while((i*)<=n){
i<<=;
if((i+)<=n && a[i+]>a[i])i++;
if(a[i]>a[i/])swap(a[i],a[i/]);
else break;
}
} void headSort(int a[],int n){
head_size=n;
int i;
for(i=;i<=n;i++){
shiftUp(s,i);
}
for(i=;i<=n;i++){
temp[i]=s[];
s[]=s[n+-i];
head_size--;
shiftDown(s,,head_size);
} for(i=;i<=n;i++){
s[i]=temp[i];
}
} int main(){
int n=,i;
headSort(s,n);
for(i=;i<=n;i++){
printf("%d\n",s[i]);
} return ;
}

//这个数据量可以控制

#include<stdio.h>
#include<time.h>
#include<iostream>
using namespace std; int shu[]={,,,,,,,,,};
int newShu[]; void shiftUp(int a[],int n){
int i=n,next;
while(i>){
next=i>>;
if(a[i]>a[next])
swap(a[i],a[next]);
i=next;
}
} void shiftDown(int a[],int n){
int i=;
while((i<<)<=n){
i=i<<;
if((i+)<=n&&a[i+]>a[i])i++;
if(a[i]>a[i/])swap(a[i],a[i/]);
}
} void headSort(int n){
int i;
for(i=;i<=n;i++){
shiftUp(shu,i);
}
for(i=;i<=n;i++){
newShu[i]=shu[];
shu[]=shu[n-i+];
shiftDown(shu,n-i);
}
} int main(){
int i,n=;
srand(time(NULL));
for(i=;i<=n;i++){
shu[i]=rand()%;
printf("%d ",shu[i]);
}printf("\n"); headSort(n); for(i=;i<=n;i++){
printf("%d ",newShu[i]);
}printf("\n"); getchar();
}

希尔排序是插入排序的一种变形,是步长不短缩小的插入排序

#include<iostream>
#include<cstdio>
#include<time.h>
using namespace std;
double test[] ; void shellsort(double *s,int left,int right) {//希尔排序是插入排序的一种变形,步长逐渐缩小的插入排序
for (int step = right/ ;step>; step/=) {
for (int i = step; i <=right; i++) {
double temp = s[i];
int j = i;
while (j >= step && temp < s[j - step]) {
s[j] = s[j - step];
j -= step;
}
s[j] = temp;
}
}
}
int main(){
freopen(" data.txt","r",stdin);
time(NULL);
int i; for(i=;i<=;i++){
scanf("%lf",&test[i]);
}
shellsort(test,,); printf("第1个:%lf\n",test[]);
printf("第10个:%lf\n",test[]);
printf("第100个:%lf\n",test[]);
printf("第1000个:%lf\n",test[]);
printf("第10000个:%lf\n",test[]); return ;
}

/*插入排序与希尔排序的实例比较*/

希尔排序有时被叫做缩减增量排序(diminishing increment sort),使用一个序列h1,h2,h3……这样一个增量序列。只要h1=1时,任何增量序列都是可以的。但有些可能更好。对于希尔排序为什么会比直接插入排序快的原因,我们可以来看一个比较极端的例子:

假如对于一个数组{,,,,,,,}以从小到大的顺序来排。直接插入排序显然是很悲剧的了。

它的每次排序结果是这样的:

, , , , , , , 

, , , , , , , 

, , , , , , , 

, , , , , , , 

, , , , , , , 

, , , , , , , 

, , , , , , , 

然后我们来看看Shell排序会怎样处理,一开始步长为4

数组分为8, , , 5和4, , , 

首先是8和4进行比较,交换位置。

变成了4, , , 5和8, , , 

同理7和3,6和2,5和1也是样的,所以当步长为4时的结果是:

, , , , , , , 

可以看到,大的数都在后边了。

接下来的步长为2

这一步过程就多了很多:

一开始是4和2进行比较,交换,得到:

, , , , , , , 

3和1比较,交换,得到:

, , , , , , , 

接下来是4和8,3和7,这两个比较没有元素交换。接下来8和6,7和5就需要交换了。所以步长为2时的结果就是:

, , , , , , , 

可以明显地感觉到,数组变得“基本有序”了。

接下来的步长1,变成了直接插入排序。手动模拟一下就可以发现,元素的交换次数只有四次!这是相当可观的。也由此我们可以得到一个基本的事实:对于基本有序的数组,使用直接插入排序的效率是很高的!
转自:http://www.cnblogs.com/yjiyjige/archive/2013/08/13/3256138.html

归并排序,思考将两个有序数列变成一个有序数列的过程,归并就是由小到大重复这个过程,最终使数组有序

#include<iostream>
#include<cstdio>
#include<time.h>
using namespace std;
double test[],temp[]; void unsort(double *s,int left,int right){ int mid=(left+right)>>;
if(mid-left>=)unsort(s,left,mid);
if(right-mid>=)unsort(s,mid+,right); int i,p1=left,p2=mid+;
for(i=left;i<=right;i++){//两个有序数组变成一个有序数组
if(p1>mid){
temp[i]=s[p2];
p2++;
continue;
}
if(p2>right){
temp[i]=s[p1];
p1++;
continue;
}
if(s[p1]<=s[p2]){
temp[i]=s[p1];
p1++;
}else{
temp[i]=s[p2];
p2++;
}
}
for(i=left;i<=right;i++){ //转移
s[i]=temp[i];
}
} int main(){
freopen(" data.txt","r",stdin);
time(NULL);
int i; for(i=;i<=;i++){
scanf("%lf",&test[i]);
}
unsort(test,,); printf("第1个:%lf\n",test[]);
printf("第10个:%lf\n",test[]);
printf("第100个:%lf\n",test[]);
printf("第1000个:%lf\n",test[]);
printf("第10000个:%lf\n",test[]); return ;
}

排序 第K大等问题总结的更多相关文章

  1. 【转载】两个排序数组的中位数 / 第K大元素(Median of Two Sorted Arrays)

    转自 http://blog.csdn.net/zxzxy1988/article/details/8587244 给定两个已经排序好的数组(可能为空),找到两者所有元素中第k大的元素.另外一种更加具 ...

  2. 编写函数求整形数组a中存储的m个不重复的整数的第k大的整数(其中m>=1,1<=k<=m)很简单的一个思路是酱紫的:管他辣么多干啥,上来一把排序然后直接得答案

    /** * @author:(LiberHome) * @date:Created in 2019/2/28 20:38 * @description: * @version:$ *//*编写函数求整 ...

  3. 给定两个数组,这两个数组是排序好的,让你求这两个数组合到一起之后第K大的数。

    题目:给定两个数组,这两个数组是排序好的,让你求这两个数组合到一起之后第K大的数. 解题思路: 首先取得数组a的中位数a[aMid],然后在b中二分查找a[aMid],得到b[bMid],b[bSt] ...

  4. 【基础算法】排序-复杂排序之二(找出第K大的数)

    切割的思想是高速排序最精髓的地方.每一次切割出来的元素K一个排在第K位,所以利用这样的思想我们至少知道3点 1. 被切割出来的元素K最后一定排在第K位. 2. 在K左边的元素一定比K小或者相等. 3. ...

  5. [LeetCode] Kth Largest Element in an Array 数组中第k大的数字

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  6. 区间第K大(一)

    Problem: 给定无序序列S:[b, e),求S中第K大的元素. Solution 1.裸排序 2.现将区间均分成两段,S1, S2,对S1,S2分别排序,然后

  7. 寻找数组中的第K大的元素,多种解法以及分析

    遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因 ...

  8. [51nod1685]第k大区间

    Description 定义一个长度为奇数的区间的值为其所包含的的元素的中位数. 现给出$n$个数,求将所有长度为奇数的区间的值排序后,第$k$大的值为多少. Input 第一行两个数$n$和$k$. ...

  9. 数据结构2 静态区间第K大/第K小

    给定数组$A[1...N]$, 区间$[L,R]$中第$K$大/小的数的指将$A[L...R]$中的数从大到小/从小到大排序后的第$K$个. "静态"指的是不带修改. 这个问题有多 ...

随机推荐

  1. 简单的HelloWorld

    简单的HelloWorld 步骤: -加入jar包 -在web.xml中配置DispatcherServlet -加入Spring MVC的配置文件 新建文件springmvc.xml: -编写处理请 ...

  2. 清华大学 pip 源

    pypi 镜像使用帮助 pypi 镜像每 5 分钟同步一次. 临时使用 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-pac ...

  3. [C#]委托实例分析(附源码)

    一直都听说C#中的委托与事件非常重要,都没有什么切身的体会,而这次通过做一个WinForm二次开发的项目才真正感觉到了委托与事件的犀利之处. 1.C#中的事件和委托的作用? 事件代表一个组件能够被关注 ...

  4. Prism 4 文档 ---第10章 Silverlight和WPF之间共享代码

        本主题帮助你理解来自Prism的多目标和它的优缺点.多目标的代码针对两个不同的平台有大致相同的代码库.这允许同时保持代码尽可能多一样能够产生针对两种不同技术的二进制文件.在这种情况下,本节介绍 ...

  5. 学习写domready

    原视频参考http://www.imooc.com/learn/488 --博主个人尝试学习写的-- /** * Created by ty on 2016/1/3. */ //尝试自己写domrea ...

  6. Linux设备驱动——简单的字符驱动

    本文介绍Linux字符设备的静态注册方法, 其中涉及到的模块加载,不了解的可以先参考 构建和运行模块 1. 还是线上源代码: //memdev.h #ifndef _MEMDEV_H_ #define ...

  7. AS3帮助手册

    http://help.adobe.com/zh_CN/FlashPlatform/reference/actionscript/3/index.html

  8. c# Request.Files["xx"]取不到值解决办法

  9. visual studio 调试时提示 已加载“C:\Windows\SysWOW64\ntdll.dll”。无法查找或打开 PDB 文件。

    问题描述 “Win32Project3.exe”(Win32): 已加载“D:\software\VS2013\VS2013 文档\Win32Project3\Debug\Win32Project3. ...

  10. 《Drools7.0.0.Final规则引擎教程》第4章 4.6 结果条件

    结果条件 在Java中,如果有重复的代码我们会考虑进行重构,抽取公共方法或继承父类,以减少相同的代码在多处出现,达到代码的最优管理和不必要的麻烦.Drools同样提供了类似的功能.下面我们以实例来逐步 ...