1.排序比较
稳定的排序:
冒泡排序、鸡尾酒排序(双向的冒泡)、插入排序、归并排序、桶排序、基数排序、二叉树排序、图书馆排序
不稳定:
选择排序、希尔排序、堆排序、快速排序
复杂度nlogn:归并、二叉树、图书馆、希尔、快排最好情况
复杂度n2: 冒泡,鸡尾酒,插入,选择,快排最坏情况
复杂度n:桶排序、基数排序
2.插入排序
将一个记录插入到已经排好序的有序表中,设立哨兵作为临时存储和判断数边界。
#include<iostream>
#include<stdlib.h>
using namespace std;
void InsertionSort(int *a, int len)
{
for (int j=1; j<len; ++j)
{
int key = a[j];
int i = j-1;
while (i>=0 && a[i]>key)
{
a[i+1] = a[i];
i--;
}
a[i+1] = key;
}
for(int i=0;i<len;++i)
cout<<a[i];
cout<<endl;
}
int main(int argc, const char * argv[])
{
int s[]={4,2,5,7,1,8,0,4,9};
InsertionSort(s,9);
return 0;
}
3.希尔排序
先将一组记录按照某个增量分组,对每组中全部元素进行直接插入排序,减小增量,直至为1
#include<iostream>
#include<stdlib.h>
using namespace std;
void ShellSort(int *a, int len)
{
int h = 1;
while( h<len )
h = 3*h + 1;
while( h>0 )
{
for (int j=h; j<len; j++)
{
int key = a[j];
int i = j-h;
while( i>=0 && a[i]>key )
{
a[i+h] = a[i];
i = i-h;
}
a[i+h] = key;
}
h = h/3;
}
for(int i=0;i<len;++i)
cout<<a[i];
}
int main(int argc, const char * argv[])
{
int s[]={4,2,5,7,1,8,0,4,9,3};
ShellSort(s,10);
return 0;
}
4.选择排序
选出最小的一个数与第一个位置的数交换,然后再剩下的数当中再找最小的与第二个交换
#include<iostream>
#include<stdlib.h>
using namespace std;
int selectminkey(int a[],int n,int i)
{
int k=i;
for(int j=i+1;j<n;++j)
if(a[k]>a[j])
k=j;
return k;
}
void selectsort(int a[],int n)
{
int key,tmp;
for(int i=0;i<n;++i)
{
key=selectminkey(a,n,i);
if(key!=i)
{
tmp=a[i];
a[i]=a[key];
a[key]=tmp;
}
cout<<a[i];
}
cout<<endl;
}
int main(int argc, const char * argv[])
{
int s[]={4,2,5,7,1,8,0,4,9,3};
selectsort(s,10);
return 0;
}
5.二元选择排序
//每趟确定两个元素
#include<iostream>
#include<stdlib.h>
using namespace std;
void selectsort(int r[],int n)
{
int i,j,min,max,tmp;
for(i=1;i<=n/2;++i)
{
min=max=i;
for(j=i+1;j<=n-i;j++)
{
if(r[j]>r[max])
{
max=j;
continue;
}
if(r[j]<r[min])
min=j;
}
tmp=r[i-1];
r[i-1]=r[min];
r[min]=tmp;
tmp=r[n-i];
r[n-i]=r[max];
r[max]=tmp;
}
for(i=0;i<n;i++)
cout<<r[i];
cout<<endl;
}
int main(int argc, const char * argv[])
{
int s[]={4,2,5,7,1,8,0,4,9,3};
selectsort(s,10);
return 0;
}
6.堆排序
//大顶堆,完全二叉树,建堆的过程:去掉堆顶得元素后,交换最后一个元素到堆顶,此时,不符合的话,将堆顶与左右元素中较大的元素交换。
#include<iostream>
#include<stdlib.h>
using namespace std;
void HeapAdjust(int array[],int i,int nLength)
{
int nChild;
int nTemp;
for(;2*i+1<nLength;i=nChild)
{
//子结点的位置=2*(父结点位置)+1
nChild=2*i+1;
//得到子结点中较大的结点
if(nChild<nLength-1&&array[nChild+1]>array[nChild])++nChild;
//如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
if(array[i]<array[nChild])
{
nTemp=array[i];
array[i]=array[nChild];
array[nChild]=nTemp;
}
else break; //否则退出循环
}
}
//堆排序算法
void HeapSort(int array[],int length)
{
int i;
//调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素
//length/2-1是最后一个非叶节点,此处"/"为整除
for(i=length/2-1;i>=0;--i)
HeapAdjust(array,i,length);
//从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
for(i=length-1;i>0;--i)
{
//把第一个元素和当前的最后一个元素交换,
//保证当前的最后一个位置的元素都是在现在的这个序列之中最大的
array[i]=array[0]^array[i];
array[0]=array[0]^array[i];
array[i]=array[0]^array[i];
//不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值
HeapAdjust(array,0,i);
}
for(i=0;i<length;i++)
cout<<array[i];
cout<<endl;
}
int main(int argc, const char * argv[])
{
int s[]={4,2,5,7,1,8,0,4,9,3};
HeapSort(s,10);
return 0;
}
7.交换排序
冒泡排序:相邻两个数排序
改进:1.设置标志变量pos,用于记录每趟排序中最后一次进行交换的位置,下一趟扫描到pos位置。
2.每趟排序进行正向和反向两遍冒泡 low=0;high=n-1;while(low
#include<iostream>
#include<stdlib.h>
using namespace std;
//一般的冒泡排序
void bubbleSort(int a[], int n)
{
int i, j, k;
int temp;
for (i = 0; i < n; i++){ //最多做n-1趟排序
for(j = 0 ;j < n - i - 1; j++){
if(a[j] > a[j + 1]){ //把大的值交换到后面
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
cout<<"第"<<i+1<<"次结果:";
for(k = 0; k < n; k++)
cout<<a[k]<<' ';
cout<<endl;
}
cout<<"最终排序结果:";
for(k = 0; k < n; k++)
cout<<a[k]<<' ';
cout<<endl;
}
//改进的冒泡,设置pos位置,下次循环到pos位置
void posbbleSort(int a[], int n)
{
int i=n-1,m=0;
while(i>0)
{
int pos=0;
for(int j=0;j<i;++j)
{
if(a[j]>a[j+1])
pos=j;
int tmp=a[j];
a[j]=a[j+1];
a[j+1]=tmp;
}
i=pos;
cout<<"第"<<m+1<<"次结果:";
for(int k = 0; k < n; k++)
cout<<a[k]<<' ';
m++;
cout<<endl;
}
cout<<"最终排序结果:";
for(int k = 0; k < n; k++)
cout<<a[k]<<' ';
cout<<endl;
}
//改进版的冒泡排序(双向冒泡)
void bidBubbleSort(int a[], int n)
{
int left, right, t, l, r, j, i = 0;
left =0;
right = n -1;
//双向冒泡算法,极大的减少了循环排序的次数
while(left < right)
{
//必须要给l和r赋值,否则若数组一开始就有序,则right=r中的r未赋值,即报错
l = left + 1;
r = right -1;
//第一次循环将最大的值放到末尾
for(j = left; j < right; j++)
if(a[j] > a[j + 1])
{
t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
r = j;
}
right = r;
//第二次循环将最小的值放到了开头
for(j = right; j > left; j--)
if(a[j] < a[j - 1])
{
t = a[j];
a[j] = a[j - 1];
a[j - 1] = t;
l = j;
}
left = l;
cout<<"第"<<i+1<<"次结果:";
for(int k = 0; k < n; k++)
cout<<a[k]<<' ';
i++;
cout<<endl;
}
cout<<"最终排序结果:";
for(int k = 0; k < n; k++)
cout<<a[k]<<' ';
cout<<endl;
}
int main(int argc, const char * argv[])
{
int s1[]={4,2,5,7,1,8,0,4,9,3};
int s2[]={4,2,5,7,1,8,0,4,9,3};
int s3[]={4,2,5,7,1,8,0,4,9,3};
bubbleSort(s1,10);
posbbleSort(s2,10);
bidBubbleSort(s3,10);
return 0;
}
8.快排
选择一个基准,一趟分为两组,左小右大,后对两部分分别用同样的方法
#include<iostream>
#include<stdlib.h>
using namespace std;
void quickSort(int * arrs, int left, int right){
int oldLeft = left;
int oldRight = right;
bool flag = true;
int baseArr = arrs[oldLeft];
while (left < right){
while (left < right && arrs[right] >= baseArr){
right--;
flag = false;
}
arrs[left] = arrs[right];
while (left < right && arrs[left] <= baseArr){
left++;
flag = false;
}
arrs[right] = arrs[left];
}
arrs[left] = baseArr;
if (!flag){
quickSort(arrs, oldLeft, left-1);
quickSort(arrs, left+1, oldRight);
}
}
int main(int argc, const char * argv[])
{
int s[]={4,2,5,7,1,8,0,4,9,3};
quickSort(s,0,9);
for (int i=0;i<10;i++)
cout<<s[i]<<endl;;
return 0;
}
9.归并排序
归并排序是采用分治法的一个非常典型的应用,它要做两件事情:
第一: “分”, 就是将数组尽可能的分,一直分到原子级别。
第二: “并”,将原子级别的数两两合并排序,最后产生结果。
至于二个有序数列合并,只要比较二个数列的第一个数,谁小就先取谁安放到临时队列中,取了后将对应数列中这个数删除,直到一个数列为空,再将另一个数列的数据依次取出即可。
//将待待排序列分为若干子序列,每个子序列有序,再把有序子序列合并为整体有序列。
#include<stdlib.h>
#include<iostream>
using namespace std;
void mergeArray(int * arrs, int * tempArr, int left, int middle, int right){
int i = left, j = middle ;
int m = middle + 1, n = right;
int k = 0;
while(i <= j && m <= n){
if(arrs[i] <= arrs[m])
tempArr[k++] = arrs[i++];
else
tempArr[k++] = arrs[m++];
}
while(i <= j)
tempArr[k++] = arrs[i++];
while(m <= n)
tempArr[k++] = arrs[m++];
for(i=0; i < k; i++)
arrs[left + i] = tempArr[i];
}
void mergeSort(int * arrs, int * tempArr, int left, int right){
if(left < right){
int middle = (left + right)/2;
mergeSort(arrs, tempArr, left, middle);
mergeSort(arrs, tempArr, middle + 1, right);
mergeArray(arrs, tempArr, left, middle, right);
}
}
int main(int argc, const char * argv[])
{
int s[]={4,2,5,7,1,8,0,4,9,3};
int tmp[10];
mergeSort(s,tmp,0,9);
for (int i=0;i<10;i++)
cout<<s[i]<<' ';
return 0;
}