一、冒泡排序
时间复杂度:O(N²)
原理:从数组的第一个位置开始两两比较array[index]和array[index+1],如果array[index]大于array[index+1]则交换array[index]和array[index+1]的位置,直到数组结束。
void Bubble(int array[], int size) { int i,j; for(i=0; i<size; i++) { for(j=i+1; j<size; j++) { if(array[i]>array[j]) { array[i]=array[i]^array[j]; array[j]=array[i]^array[j]; array[i]=array[j]^array[i]; } } }
二、选择排序
时间复杂度:O(N^2),与冒泡排序相比减少了数组交换的次数
原理:选择一个 array[0]作为标杆,然后循环找到除这个外最小的 (查找小于标杆的最小 ),交换这两个,这时最小就被放到了array[0]上,然后再将array[1]作为标杆,从剩下未排序的 中找到最小 ,并交换。
void Sort(int array[], int size) { int i,j,k; for(i=0; i<size; i++) { k=i; for(j=i+1; j<size; j++) { if(array[j]<array[k]) { k=j; } } if(i!=k) { array[i]=array[i]^array[k]; array[k]=array[k]^array[i]; array[i]=array[i]^array[k]; } } }
三、插入排序
时间复杂度:插入排序对随即顺序的序列的时间复杂度也为O(N^2),但是对于基本有序的序列进行排序时间复杂度为O(N)
适用:一般不用在数据大于1000的场合或者重复排序超过200数据项的序列使用插入排序
原理:插入排序的思想是数组是部门有序的,然后将无序的部分循环插入到已有序的序列中。
void InsertSort(int array[], int size) { int i,j,temp; for(i=2; i<size; i++) { temp=array[i]; for(j=i-1; j>=0 && array[j]>temp; j--) { array[j+1]=array[j]; } array[j+1]=temp; } }
四、希尔排序/缩小增量排序
时间复杂度:n的1.2次幂
适用:适合于数据量在5000以下并且速度并不是特别重要的场合。
原理:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
void shellSort(int array[], int size) { int i,j,temp; int increment=size; do { increment=increment/3+1; for(i=increment+1; i<size; i++) { temp=array[i]; for(j=i-increment; j>=0 && array[j]>temp; j-=increment) { array[j+increment]=array[j]; } array[j+increment]=temp; } }while(increment>1); }
五、堆排序
时间复杂度:O(N*logN)
适用:适合于数据量非常大的场合(百万数据)
原理:利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。
其基本思想为(大顶堆):
1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无须区;
2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
//array是待调整的堆数组,i是待调整的数组元素的位置,nlength是数组的长度 //本函数功能是:根据数组array构建大根堆 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); } }