1 - 引言
虽然C++中的STL库中提供了许多排序和查找的方法。但是我们还是需要了解一下排序和查找内部的原理,下面让我们学习一下各类排序与查找算法
2 - 归并排序
第一种高效的排序算法是归并排序,按照分治三步法,对归并排序算法介绍如下:
- 划分问题:把序列分成元素个数尽量相等的两半。
- 递归求解:把两半元素分别排序
- 合并问题:把两个有序表合并成一个
前两部分是很容易完成的,关键在于如何把两个有序表合成一个。如图所示,每次只需把两个序列的最小元素加以比较,删除其中较小元素并加入合并后的新表即可。由于需要一个新表来存放结果,所以附加空间为N
#include<cstdio>
const int maxn = 1000;
int A[maxn];
int T[maxn]={0};
void merge_sort(int* A,int x,int y,int* T){
if(y-x>1){
int m = x+(y-x)/2; //划分
int p=x, q=m,i=x;
merge_sort(A,x,m,T);
merge_sort(A,m,y,T);
while(p<m||q<y){
if(q>=y||(p<m&&A[p]<=A[q])) T[i++] = A[p++];//从左半数组赋值到临时空间
else T[i++] = A[q++]; //右半数组复制到临时空间
}
for(i=x;i<y;i++) A[i] = T[i]; //从辅助空间复制回A数组
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&A[i]);
merge_sort(A,0,n,T);
for(int i=0;i<n;i++)
printf("%d",A[i]);
return 0;
}
3 - 快速排序
快速排序是最快的通用内部排序算法,且速度比归并排序块且不需要辅助空间。分成三步骤来实现。
- 划分问题:把数组的各个元素重排后分成左右两部分,使得左边的任意元素都小于或等右边的任意元素
- 递归求解:把左右两部分分别排序
- 合并问题:不用合并,因为此时数组已经完全有序
//快速排序实现
#include<stdio.h>
#include<stdlib.h>
const int maxn = 1000;
int A[maxn];
void quick_sort(int s[],int l,int r)
{
if(l < r)
{
int i=l,j=r,x=s[l];
while(i<j)
{
while(i<j && s[j]>=x)//从右到左找到第一个小于x的数
j--;
if(i<j)
s[i++]=s[j];
while(i<j && s[i]<=x)//从左往右找到第一个大于x的数
i++;
if(i<j)
s[j--]=s[i];
}
s[i]=x;//i = j的时候,将x填入中间位置
quick_sort(s,l,i-1);//递归调用
quick_sort(s,i+1,r);
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&A[i]);
quick_sort(A,1,n);
for(int i=1;i<=n;i++)
printf("%d",A[i]);
return 0;
}
4 - 二分查找
//快速排序实现
#include<stdio.h>
#include<stdlib.h>
const int maxn = 1000;
int A[maxn];
/**
* 二分查找,找到该值在数组中的下标,否则为-1
*/
int bsearch(int*A, int x, int y, int v){
int m;
while(x < y) {
m = x+(y-x)/2;
if(A[m] == v) return m;
else if(A[m] > v) y = m;
else x = m+1;
}
return -1;
}
int main()
{
int n,key,m;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&A[i]);
scanf("%d",&key);
m=bsearch(A,1,n+1,key);
printf("%d ",m);
return 0;
}