排序算法小结

来源:互联网 发布:硬盘数据恢复最好软件 编辑:程序博客网 时间:2024/05/22 04:44

1、冒泡排序

冒泡排序的基本思想:两两比较相邻记录的关键字,如果反序则交换,知道没有反序的记录为止。

//冒泡排序,升序public static void bubbleSort0(int[] array){for(int i=0;i<array.length-1;i++){for(int j=i+1;j<array.length;j++){if(array[i]>array[j])swap(array,i,j);}}}//优化public static void bubbleSort1(int[] array){for(int i=0;i<array.length;i++){for(int j=array.length-1;j>i;j--){//j从后往前循环if(array[j-1]>array[j])//若前者大于后者swap(array,j-1,j);}}}//优化/** * 思路:增加一个标记变量flag。当flag=false时,表示没有任何数据进行交换时,序列有序,则退出循环。 * @param array */public static void bubbleSort2(int[] array){boolean flag=true;for(int i=0;i<array.length&&flag;i++){//当flag为false,不满足循环的条件,则退出循环。即没有再进行交换数据,则表明序列有序。flag=false;for(int j=array.length-1;j>i;j--){//j从后往前循环if(array[j-1]>array[j]){//若前者大于后者swap(array,j-1,j);flag=true;}}}}public static void swap(int[] array,int i,int j){int temp=array[i];array[i]=array[j];array[j]=temp;}

2、简单选择排序

.选择排序的基本思想:每一趟在n-i+1 (i=1,2,…,n-1)个记录中选择关键字最小的记录作为有序序列的第i个记录。

//简单选择排序public static void selectSort(int[] array){int min=0;for(int i=0;i<array.length-1;i++){min=i;for(int j=i+1;j<array.length;j++){if(array[min]>array[j]){min=j;}}if(i!=min)swap(array,i,min);}}public static void swap(int[] array,int i,int j){int temp=array[i];array[i]=array[j];array[j]=temp;}

3、直接插入排序

直接插入排序的基本操作:将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。

/** * 思路:array[0]设为哨兵。 * @param array */public static void insertSort(int[] array){int j=0;for(int i=2;i<array.length;i++){if(array[i]<array[i-1]){array[0]=array[i];for(j=i-1;array[j]>array[0];j--){array[j+1]=array[j];}array[j+1]=array[0];}}}

4、希尔排序

基本思想:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序。

//希尔排序,升序public static void shellSort(int[] array){int i,j;int increment=array.length;do{increment=increment/3+1;for(i=increment+1;i<array.length;i++){if(array[i]<array[i-increment]){array[0]=array[i];for(j=i-increment;j>0&&array[j]>array[0];j-=increment)array[j+increment]=array[j];array[j+increment]=array[0];}}}while(increment>1);}

5、堆排序

堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子节点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,成为小顶堆。

堆排序的基本思想:将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值。如此反复执行,就能得到一个有序序列。

/** * 思路:array[0]为哨兵。 * @param array */public static void heapSort(int[] array){for(int i=(array.length-1)/2;i>0;i--){heapAdjust(array,i,array.length-1);//调整为大顶堆}for(int i=array.length-1;i>1;i--){swap(array,1,i);//将堆顶记录和当前未经排序的子序列的最后一个记录交换heapAdjust(array, 1, i-1);//重新调整为大顶堆}}//调整为大顶堆public static void heapAdjust(int[] array,int s,int m){array[0]=array[s];for(int j=2*s;j<=m;j*=2){//沿关键字较大的孩子节点向下筛选if(j<m&&array[j]<array[j+1])j++;//j为关键字较大的记录的下标if(array[0]>=array[j])break;array[s]=array[j];s=j;}array[s]=array[0];//插入}public static void swap(int[] array,int i,int j){int temp=array[i];array[i]=array[j];array[j]=temp;}

6、归并排序

归并排序的基本原理:假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到(n/2取上限)个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,称为 2路归并排序。

递归

//递归法public static void mergeSort(int[] array){MSort(array,array,0,array.length-1);}//将SR[s...t]归并为TR1[s...t]public static void MSort(int[] SR,int[] TR1,int s,int t){int[] TR2=new int[SR.length];if(s==t){TR1[s]=SR[s];}else{int m=(s+t)/2;//将SR[s...t]平分为SR[s...m]和SR[m+1...t]MSort(SR,TR2,s,m);//递归将SR[s...m]归并为有序的TR2[s...m]MSort(SR,TR2,m+1,t);//递归将SR[m+1...t]归并为有序的TR2[m+1...t]Merge(TR2,TR1,s,m,t);//将TR2[s...m]和TR2[m+1...t]归并到TR1[s...t]}}//将有序的SR[i...m]和SR[m+1...n]归并到TR[i...n]public static void Merge(int[] SR,int[] TR,int i,int m,int n){int k=0;//TR的下标int j=0;for(k=i,j=m+1;i<=m&&j<=n;k++){//将SR中的记录升序归并如TRif(SR[i]<SR[j]){TR[k]=SR[i++];}else{TR[k]=SR[j++];}}if(i<=m){for(int l=0;l<=m-i;l++){//将剩余的SR[i...m]复制到TRTR[k+l]=SR[i+l];}}if(j<=n){for(int l=0;l<=n-j;l++){//将剩余的SR[m+1...n]复制到TRTR[k+l]=SR[j+l];}}}

非递归

//非递归法public static void mergeSort2(int[] array){int[] TR=new int[array.length];int k=1;while(k<array.length){MergePass(array, TR, k, array.length-1);k=2*k;//子序列长度加倍MergePass(TR, array, k, array.length-1);k=2*k;}}public static void MergePass(int[] SR,int[] TR,int s,int n){int i=0;while(i<=n-2*s+1){Merge(SR,TR,i,i+s-1,i+2*s-1);i+=2*s;}if(i<n-s+1)Merge(SR,TR,i,i+s-1,n);elsefor(int j=i;j<=n;j++)TR[j]=SR[j];}//将有序的SR[i...m]和SR[m+1...n]归并到TR[i...n]public static void Merge(int[] SR,int[] TR,int i,int m,int n){int k=0;//TR的下标int j=0;for(k=i,j=m+1;i<=m&&j<=n;k++){//将SR中的记录升序归并如TRif(SR[i]<SR[j]){TR[k]=SR[i++];}else{TR[k]=SR[j++];}}if(i<=m){for(int l=0;l<=m-i;l++){//将剩余的SR[i...m]复制到TRTR[k+l]=SR[i+l];}}if(j<=n){for(int l=0;l<=n-j;l++){//将剩余的SR[m+1...n]复制到TRTR[k+l]=SR[j+l];}}}

7、快速排序

public static void quickSort(int[] array){qSort(array, 0, array.length-1);}public static void qSort(int[] array,int low,int high){if(low<high){int pivot=partition(array, low, high);//将array一分为二,算出枢轴值pivotqSort(array, low, pivot-1);//对低子表递归排序qSort(array, pivot+1, high);//对高子表递归排序}}/** * 交换子表的记录,使枢轴记录到位,并返回其所在位置,此时,在它之前(后)的记录均不大(小)于它。 * @param array * @param low * @param high * @return */public static int partition(int[] array,int low,int high){int pivotkey=array[low];//用第一个记录作为枢轴记录while(low<high){//从两端向中间扫描while(low<high&&pivotkey<=array[high])high--;swap(array,low,high);//将比枢轴记录小的记录交换到低端while(low<high&&pivotkey>=array[low])low++;swap(array, low, high);//将比枢轴记录大的记录交换到高端}return low;//返回枢轴所在位置}public static void swap(int[] array,int i,int j){int temp=array[i];array[i]=array[j];array[j]=temp;}

优化:

//优化/** * 思路:三数取中,替换 * @param array * @param low * @param high * @return */public static int partition2(int[] array,int low,int high){//三数取中int m=low+(high-low)/2;//计算数组的中间元素的下标if(array[low]>array[high])swap(array,low,high);if(array[m]>array[high])swap(array,m,high);if(array[low]>array[m])swap(array,low,m);int pivotkey=array[low];//用第一个记录作为枢轴记录array[low]=pivotkey;//将枢轴关键字被分到array[0]while(low<high){//从两端向中间扫描while(low<high&&pivotkey<=array[high])high--;array[low]=array[high];//替换!!!while(low<high&&pivotkey>=array[low])low++;array[high]=array[low];//替换!!!}return low;//返回枢轴所在位置}


0 0