1、冒泡排序
(1)基本思想:当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。
(2)分析:改进代码中,最好的情况下(数组有序),时间复杂度O(n)。最坏O(n2)。因为是两两相邻比较,冒泡排序稳定。
<span style="font-size:14px;">pac</span>kage com.ys.sort;
public class BubbleSort {
public void bubbleSort(int[] a){
int i,j;
for(i = 0; i < a.length;i++){
for(j = a.length - 1; j > i;j--)
if(a[j]>a[j-1])
swap(a,j,j-1);
}
}
public void swap(int[] a,int s,int m){
int temp = a[s];
a[s] = a[m];
a[m] = temp;
}
}
package com.ys.sort;
/*
* 冒泡排序优化
* 待排序序列有序时,不需要继续后面的循环。循环一遍即可。
* */
public class BubbleSort2 {
public void bubbleSort(int[] a){
int i,j;
boolean flag = true;
for(i = 0; i < a.length && flag;i++){
flag = false;
for(j = a.length - 1; j > i;j--)
if(a[j]>a[j-1]){
swap(a,j,j-1);
flag = true;
}
}
}
public void swap(int[] a,int s,int m){
int temp = a[s];
a[s] = a[m];
a[m] = temp;
2、选择排序
(1)基本思想:选择排序是从待排序的数中选出最小的放在已经排好的后面。
(2)时间复杂度O(n2),最大的特点是交换移动数据次数相对少。不稳定。
package com.ys.sort;
public class SelectSort {
public void selectSort(int[] a) {
int i, j, min;
for (i = 0; i < a.length - 1; i++) {
min = i;
for (j = i + 1; j < a.length; j++){
if (a[j] < a[min])
min = j;
}
if (min != i)
swap(a,i,min);
}
}
public void swap(int[] a,int s,int m){
int temp = a[s];
a[s] = a[m];
a[m] = temp;
}
}
3、插入排序
(1)基本思想:将一个记录插入到已经排好序的有序表中。
(2)思路上从待排序的数据中选出一个,插入到前面合适的位置,耗时点在插入方面,合适的位置意味着我们需要进行比较找出哪是合适的位置,举个例子:对于9,2,7,19,100,97,63,208,55,78这组数,第一个数9前面没有,不做操作,当第一个数完后,剩下的数就是待排序的数,我们将要从除去9开始的数中选出一个插入到前面合适的位置,拿到2后,2比9小,放在temp上,通过循环找出这个合适的位置,发现比temp大的数,立即将该数向后移动一位(这样做的目的是:前面需要空出一位来进行插入),最后通过注释3处的代码将数插入。
(3)本排序适合:基本有序的数据。好的情况下,时间复杂度O(n),平均和最坏都是O(n2)。
package com.ys.sort;
public class InsertSort {
public void insertSort(int[] a){
int i,j;
int temp = 0;
for(i=1;i<a.length;i++){
if(a[i]<a[i-1]){
temp = a[i];
for(j = i-1;j >=0 && a[j] > temp;j--)
a[j+1] = a[j];
a[j+1] = temp;
}
}
}
}
4、堆排序
(1)堆是一个完全二叉树。堆分为两种,大顶堆和小顶堆(最小堆、小根堆)。大顶堆就是堆顶元素是整个堆中最大的,每个结点的值都大于或等于其左右孩子结点。小顶堆的意思是堆顶元素是整个堆中最小的,每个结点的值都小于或等于其左右孩子结点的值。
(2)算法的过程:第一步,建堆,从一个数组顺序读取元素,建立一个堆(假设大顶堆)
第二步,堆顶元素出堆,即将堆顶元素和堆底元素交换,堆中的最大值放到了数组最后。重新调整堆使其成为大顶堆。
(3)最好、最坏和平均时间复杂度为O(nlogn),不稳定。
初始构建堆所需比较次数较多,并不适合待排序序列个数较少的情况。
package com.ys.sort;
import java.util.Arrays;
/*
* 利用《大话数据结构》堆排序进行修改
* 注意java中数组从0开始,节点s对应左右孩子是2s+1,2s+2;
* */
public class HeapSort2 {
public void heapSort(int[] array){
maxHeapAdjust(array); //构建成大顶锥
for(int i=array.length-1;i>0;i--){
swap(array,0,i);
heapAdjust(array,0,i-1); //重新调整为大顶堆
}
}
public void maxHeapAdjust(int[] array){
for(int i=array.length/2;i>=0;i--){//构建成大顶锥
heapAdjust(array,i,array.length-1);
}
}
public void heapAdjust(int[] a,int s,int m){
int temp,i;
temp = a[s]; //表示第s个节点
for(i=2*s+1;i<=m;i=2*i+1){
if(i<m && a[i]<a[i+1])
++i;
if(temp>=a[i])
break;
a[s] = a[i];
s = i;
}
a[s] = temp;
}
public void swap(int[] array,int from,int to){
int temp;
temp = array[from];
array[from] = array[to];
array[to] = temp;
}
public static void main(String[] args) {
HeapSort2 h = new HeapSort2();
int[] a= {2,16, 14, 10, 8, 7, 9, 3,13, 4};
h.heapSort(a);
String intArrayString = Arrays.toString(a); //将数组转换为字符串打印输出
System.out.print(intArrayString);
}
}
5、归并排序
(1)利用归并的思想实现的排序方法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
(2)基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。
(3)时间复杂度O(nlogn),空间复杂度O(n+logn)。稳定
package com.ys.sort;
import java.util.Arrays;
public class MergeSort {
//归并排序
public static void mergeSort(int[] arr){
int[] temp =new int[arr.length];
msort(arr, temp, 0, arr.length-1);
}
private static void msort(int[] a, int[] b, int left, int right){
//当left==right的时,已经不需要再划分了
if (left<right){
int middle = (left+right)/2;
msort(a, b, left, middle); //左子数组
msort(a, b, middle+1, right); //右子数组
merge(a, b, left, middle, right); //合并两个子数组
}
}
// 合并两个有序子序列 arr[left,..., middle] 和 arr[middle+1,..., right]。temp是辅助数组。
private static void merge(int arr[], int temp[], int left, int middle, int right){
int i=left;
int j=middle+1;
int k=0;
while ( i<=middle && j<=right){
if (arr[i] <=arr[j]){
temp[k++] = arr[i++];
}
else{
temp[k++] = arr[j++];
}
}
while (i <=middle){
temp[k++] = arr[i++];
}
while ( j<=right){
temp[k++] = arr[j++];
}
//把数据复制回原数组
for (i=0; i<k; ++i){
arr[left+i] = temp[i];
}
}
public static void main(String[] args) {
int[] a={5,6,8,9,7,8,8,8,3,10};
mergeSort(a);
String intArrayString = Arrays.toString(a); //将数组转换为字符串打印输出
System.out.print(intArrayString);
}
}
6、快速排序
(1)基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,达到排序目的。
(2)最好和平均O(nlogn),最坏O(n2)。空间复杂度最好O(logn),最坏O(n)。
package com.ys.sort;
import java.util.Arrays;
public class QuickSort {
public void quickSort(int[] a){
qSort1(a,0,a.length-1);
}
public void qSort1(int[] a,int low,int high){
int pivot;
while(low<high){
pivot = partition1(a,low,high);//枢轴值,左边的值比它小,右边的值比它大
qSort1(a,low,pivot-1);
low = pivot + 1;
}
}
/*
* 取得枢轴值
* */
public int partition1(int[] a,int low,int high){
pivotSort(a,low,high);
int pivotkey =a[low];
int temp = pivotkey;
while(low<high){
while(low<high && a[high]>=pivotkey)
high--;
a[low] = a[high];
while(low<high && a[low]<=pivotkey)
low++;
a[high] = a[low];
}
a[low] = temp;
return low;
}
/*
* 三数取中,优化选取枢轴值
* */
public void pivotSort(int[] a,int low,int high){
int m = low + (high-low)/2;
if(a[low]>a[high])
swap(a,low,high);
if(a[m]>a[high])
swap(a,m,high);
if(a[m]>a[low])
swap(a,m,low);
}
public void swap(int[] a,int s,int t){
int temp = a[s];
a[s] = a[t];
a[t] = temp;
}
public static void main(String[] args) {
int[] a={5,6,8,9,7,4,1,2,3};
QuickSort m = new QuickSort();
m.quickSort(a);
String intArrayString = Arrays.toString(a); //将数组转换为字符串打印输出
System.out.print(intArrayString);
}
}
本文中图片和部分解释转载自http://blog.csdn.net/zhangerqing/article/details/8831542