气泡、快速、插入、希尔、选择、堆、归并、基数排序。
八种排序的原理及其实现:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <stdlib.h>
#include <ctime>
#include <algorithm>
using namespace std;
const int maxn=100010;
const int inf=2<<30;
typedef int keytype;
struct records{
keytype key;
};
typedef records List[maxn];
keytype A[maxn];
void Swap(records &x,records &y){
records w;
w=x,x=y,y=w;
}
//冒泡
void Bubble_sort(int n,List &A){
for(int i=1;i<=n;i++)
for(int j=n;j>=i+1;j--)
if(A[j].key < A[j-1].key)
Swap(A[j],A[j-1]);
}
//快速排序
int FindPivot( int i, int j,List A) /* 设A是外部数组*/
/*若A[i] A[j]的关键字全部相同,则返回0; 若A[i],…A[j]的关键字全部相同,则返回0;
否则,左边两个不同关键字中的较大者的下标。*/
{
keytype firstkey = A[i].key ; /* 第1个关键字的值A[i].key*/
int k ; /* 从左到右查找不同的关键字*/
for ( k=i+1 ; k<=j; k++ ) /* 扫描不同的关键字*/
if ( A[k].key > firstkey ) /* 选择较大的关键字*/
return k ;
else if ( A[k].key < firstkey )
return i ;
return 0;
}
int Partition( int i , int j , keytype pivot,List A )
/*划分A[i] A[j] 是关键字<i t的在左子序列 划分A[i],…,A[j],是关键字<pivot 的在左子序列,
关键pivot 的在右子序列,返回有子序列的起始下标*/
{
int l , r;
do
{
for(l=i; A[l].key < pivot ; l++ );
for(r=j; A[r].key>=pivot ; r--);
if( l< r) swap(A[l],A[r]);
}
while(l <= r);
return l;
}
void QuickSort(int i,int j,List &A)
{
keytype pivot;
int k; //关键字大于等于pivot的记录在序列中的起始下标 int k; //关键字大于等于pivot的记录在序列中的起始下标
int pivotindex ; //关键字为pivot的记录在数组A中的下标
pivotindex=FindPivot(i,j,A);
if( pivotindex != 0 ) //递归终止条件
{
pivot=A[pivotindex].key;
k=Partition (i,j,pivot,A);
QuickSort(i,k-1,A);
QuickSort(k, j,A);
}
}
//插入排序
void IN_sort(int n,List A){
int i,j;
A[0].key=-1;
for(i=1;i<=n;i++){
j=i;
while(A[j].key<A[j-1].key){
Swap(A[j],A[j-1]);
j=j-1;
}
}
}
//选择排序
void Choose_sort(int n,List A){
keytype lowkey;
int lowindex;
for(int i=1;i<=n;i++){
lowindex=i;
lowkey=A[i].key;
for(int j=i;j<=n;j++){
if(A[j].key<lowkey){
lowkey=A[j].key;
lowindex=j;
}
}
Swap(A[i],A[lowindex]);
}
}
//希尔排序
void Shell_Sort(int n,List A)
{
int i, j, d;
for (d=n/2; d>=1; d=d/2) {
for (i=d+1; i<=n; i++) { //将A[i]插入到所属的子序列中
A[0].key= A[i].key; //暂存待插入记录
j=i-d; //j指向所属子序列的最后一个记录 j=i-d; //j指向所属子序列的最后 个记录
while (j>0 && A[0].key< A[j].key) {
A[j+d]= A[j];//记录后移d个位置 [j ] [j]; 记录后移个位置
j=j-d; //比较同一子序列的前一个记录
}
A[j+d]= A[0];
}
}
}
//归并排序
void Merge(int s , int m , int t , List A , List B) /*将有序序列AA和A1A合并为 个有序序列 */ /*将有序序列A[s],…,A[m]和A[m+1],…,A[t]合并为一个有序序列B[s],…,B[t]*/
{
int i = s ;
int j = m+1;
int k = s ;//置初值
/* 两个序列非空时,取小者输出到B[k]上*/
while ( i <= m && j <= t )
B[k++] = ( A[ i ].key <= A[ j ].key) ? A[i++] : A[j++] ;
/*若第一个子序列非空(未处理完),则复制剩余部分到B*/ /*若第 个子序列非空(未处理完),则复制剩余部分到B */
while ( i <= m )
B[k++] = A[i++];
/*若第二个子序列非空(未处理完) 则复制剩余部分到B*/ /* 若第二个子序列非空(未处理完),则复制剩余部分到B */
while ( j <= t )
B[k++] = A[j++];
}
void MergePass(int n , int h , List A , List B)
{
int i;
for ( i=1 ; i+2*h-1<= n; i+=2*h)
Merge(i, i+h-1, i+2*h-1, A, B) ;//归并长度为h的两个有序子序列
if ( i+h-1< n) /* 尚有两个子序列,其中最后一个长度小于h*/
Merge( i, i+h-1, n, A, B) ; /* 归并最后两个子序列*/
else /* 若i<= n且i+h-1>= n时,则剩余一个子序列轮空,直接复制*/
for (int t= i ; t<= n ; t++ )
B[t] = A[t] ;
}
void MergeSort(int n,List A){
int h=1;
List B;
while(h<n){
MergePass(n,h,A,B);
h=2*h;
MergePass(n,h,B,A);
h=2*h;
}
}
//堆排序
void PushDown(int first,int last,List A){
int r=first;
while(r<=last/2){
if((r==last/2) && (last%2)==0){//r有一个儿子,在2*r
if(A[r].key>A[2*r].key)
Swap(A[r],A[2*r]);
r=last;
}
else if((A[r].key>A[2*r].key) && (A[2*r].key<=A[2*r+1].key)){ //与左儿子交换
Swap(A[r],A[2*r]);
r=2*r;
}
else if((A[r].key>A[2*r].key) && (A[2*r].key>A[2*r+1].key)){ //与右儿子交换
Swap(A[r],A[2*r+1]);
r=2*r+1;
}
else r=last;
}
}
void Dui_Sort(int n,List A){
for(int i=n/2;i>=1;i--) //建立初始堆(堆逐渐扩大)
PushDown(i,n,A);
for(int i=n;i>=2;i--){
Swap(A[1],A[i]); //根置于末尾
PushDown(1,i-1,A);
}
}
#define RADIX_10 10 //整形排序
#define KEYNUM_31 10 //关键字个数,这里为整形位数
int GetNumInPos(int num,int pos)
{
int temp = 1;
for (int i = 0; i < pos - 1; i++)
temp *= 10;
return (num / temp) % 10;
}
void RadixSort(int* pDataArray, int iDataNum)
{
int *radixArrays[RADIX_10]; //分别为0~9的序列空间
for (int i = 0; i < 10; i++)
{
radixArrays[i] = (int *)malloc(sizeof(int) * (iDataNum + 1));
radixArrays[i][0] = 0; //index为0处记录这组数据的个数
}
for (int pos = 1; pos <= KEYNUM_31; pos++) //从个位开始到31位
{
for (int i = 0; i < iDataNum; i++) //分配过程
{
int num = GetNumInPos(pDataArray[i], pos);
int index = ++radixArrays[num][0];
radixArrays[num][index] = pDataArray[i];
}
for (int i = 0, j =0; i < RADIX_10; i++) //收集
{
for (int k = 1; k <= radixArrays[i][0]; k++)
pDataArray[j++] = radixArrays[i][k];
radixArrays[i][0] = 0; //复位
}
}
}
List L1,L2,L3,L4,L5,L6,L7;
int L8[maxn];
int main(){
int n;
int x;
n=maxn;
for(int i=1;i<=n;i++){
x=rand()%100010;
L1[i].key=L2[i].key=L3[i].key=L4[i].key=L5[i].key=L6[i].key=L7[i].key=x;
L8[i-1]=x;
}
double st[10];
st[1]=clock();
Bubble_sort(n,L1);
st[2]=clock();
IN_sort(n,L2);
st[3]=clock();
Choose_sort(n,L3);
st[4]=clock();
Shell_Sort(n,L4);
st[5]=clock();
MergeSort(n,L5);
st[6]=clock();
QuickSort(1,n,L6);
st[7]=clock();
Dui_Sort(n,L7);
st[8]=clock();
RadixSort(L8,n);
st[9]=clock();
printf("Bubble\tIn_sort\t Choose\t Shell\t Merge\t Quick\t Dui_sort\tRadixSort\n");
for(int i=1;i<=8;i++)
printf("%lf ",st[i+1]-st[i]);
return 0;
}