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

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

//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. 2.spring cloud eureka client配置

    红色加粗内容表示修改部分 1.把server项目打成jar包并启动 在项目根目录cmd执行  mvn clean package -Dmaven.test.skip=true mavne仓库地址建议 ...

  2. 031——VUE中表单控件处理之使用vue控制input和textarea表单项

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. C#学习历程(四)[实际问题]

    >>无法直接启动带有”类库输出类型”的项目 在编辑界面的右侧会出现[解决方案资源管理器],里面显示我们的程序项目和所有代码文件. 右键点击项目,在右键菜单中选择[属性] 一般导致该问题都是 ...

  4. yum 认知及使用

    https://www.cnblogs.com/zhichaoma/p/7533247.html

  5. New Concept English there (3)

    25words/ minutes Some time ago,an interesting discovery was made by archaeologists on the Aegean isl ...

  6. vscode 实用插件

    1.Auto Rename Tag,非常实用!要修改标签名称的时候自动修改结束标签,节省一半时间,提升效率,非常棒! 2.vscode-icon,这款必须要推荐,明显提升效率的小插件,在项目文件多类型 ...

  7. c# 系统校时工具类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace HuaT ...

  8. 一张图说明HTTPS 握手过程

  9. CuratorFramework入门指南

    CuratorFramework入门指南 原文地址:https://github.com/Netflix/curator/wiki/Getting-Started CuratorFramework作为 ...

  10. hessian 协议 版本 兼容

    环境 : 服务端:  hessian 4.0.38 , spring 4.3.6 ; spring文档指出spring4.0以上的版本只能使用hessian 4.0以上的版本 客户端: hessian ...