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

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

//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. IOS-启动图和开屏广告图,类似网易

    作者:若锦 原文链接:http://www.jianshu.com/p/e52806516139 启动图是在iOS开发过程中必不可少的一个部分,很多app在启动图之后会有一张自定义的开屏广告图,点击该 ...

  2. jquery基础 笔记二

    动态创建元素 关于使用HTML DOM创建元素本文不做详细介绍, 下面举一个简单的例子: //使用Dom标准创建元素 var select = document.createElement(" ...

  3. hdu 5826 physics (物理数学,积分)

    physics Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  4. Python之Fabric

    [Fabric] Fabric是一个用Python开发的部署工具,最大特点是不用登录远程服务器,在本地运行远程命令,几行Python脚本就可以轻松部署. 安装 wget https://bootstr ...

  5. 在QT中使用静态对象

    最近做教研室的项目,需要只能存在一个接收数据的线程,那么我就想把这个线程设置成一个静态对象.但是在connect信号与槽的时候出了一点问题,最后搞好了,现在这mark一下: 比如说一个声明了一个静态的 ...

  6. LINUX中的DNS服务---DNS集群

    一.DNS集群的理解 在使用DNS的时候,为了缓解服务器的压力,会使用多个辅助DNS服务器来分担主DNS的工作.这些DNS就叫做DNS集群. 二.配置过程 1)在辅DNS中操作如下:(主机号为172. ...

  7. CUDA Samples: Ray Tracking

    以下CUDA sample是分别用C++和CUDA实现的生成光线跟踪图像,并对其中使用到的CUDA函数进行了解说,code参考了<GPU高性能编程CUDA实战>一书的第六章,CUDA各实现 ...

  8. MPAndroidChart Wiki(译文)~Part 5

    19. ChartData子类 这篇wiki主要关注ChartData子类的具体介绍.至于此部分没有提及到的ChartData的子类,代表他们没有特性功能需要介绍. BarData 方法 使用 set ...

  9. Andriod4.2 Camera 架构与实现

    1.Camera架构包括客户端和服务端,他们之间的通信采用Binder机制实现. Camera的实现主要包括本地代码和Java代码两个层次: Camera本地框架: frameworks/native ...

  10. ICE:slice语言常识整理

    ICE:Slice语言(二)--源文件和词法规则:    文件命名    Slice的源文件以.ice为扩展名.   对于大小写不区分的系统(例如DOS),文件的扩展名可以大写,也可以小写,例如Cli ...