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

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

//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. day30 主机管理-堡垒机3-操作记录

    课堂代码:https://github.com/liyongsan/git_class/tree/master/day30

  2. iptables详解(10):iptables自定义链

    前文中,我们一直在定义规则,准确的说,我们一直在iptables的默认链中定义规则,那么此处,我们就来了解一下自定义链. 你可能会问,iptables的默认链就已经能够满足我们了,为什么还需要自定义链 ...

  3. 安装使用babel-polyfill。让IE支持es6

    安装 npm install --save-dev babel-polyfill 使用 在你的代码头部加载babel-polyfill,注意一定要在你的代码开始前,第一个js文件的顶部.如果是vue在 ...

  4. Mac安装MySQLdb遇到的坑

    最近项目移植, 再进行virtualenv环境安装的时候遇到mysql-python死活安装失败 首先是这个错误: sh: /usr/local/bin/mysql_config: No such f ...

  5. 【LeetCode 110_二叉树_遍历】Balanced Binary Tree

    解法一:From top to bottom int treeHeight(TreeNode *T) { if (T == NULL) ; ; } bool isBalanced(TreeNode* ...

  6. Linux虚拟机基本操作

    ---恢复内容开始---  一.输入法调整 实现步骤:Application ------> System Tools ------>Settings ------>Rejion&a ...

  7. mybatis分页查询

    方式1: select * from table order by id limit m, n; 该语句的意思为,查询m+n条记录,去掉前m条,返回后n条记录.无疑该查询能够实现分页功能,但是如果m的 ...

  8. 《Drools7.0.0.Final规则引擎教程》Springboot+规则重新加载

    在<Drools7.0.0.Final规则引擎教程>之Springboot集成中介绍了怎样将Drools与Springboot进行集成,本篇博客介绍一下集成之后,如何实现从数据库读取规则并 ...

  9. Eclipse下搭建SWT与Swing图形界面开发环境

    一.SWT与Swing介绍 SWT(StandardWidget Toolkit)则是由Eclipse项目组织开发的一套完整的图形界面开发包,虽然当初仅仅是IBM为了编写Eclipse的IDE环境才编 ...

  10. MPAndroidChart Wiki(译文)~Part 3

    13. 图例 默认情况下,所有的图表都支持图例并且会自动生成.给图表设置完数据之后,图例会被绘制出来.图例通常由多个条目组成,每个条目由标签形式/形状表示. 自动生成的图例包含的条目数取决于不同颜色的 ...