常见的排序算法有比较排序、线性排序。比较排序包括插入排序、冒泡排序、快速排序、归并排序、堆排序等,线性排序包括计数排序、基数排序和桶排序。
插入排序
插入排序的基本思想是每步将一个待排序的记录按其排序码值的大小,插到前面已经排好的文件中的适当位置,直到全部插入完为止。其最差时间复杂度O(n2),平均时间复杂度为O(n2),为稳定排序算法。Java实现的代码如下:
package sortTest;
public class InsertionSort
{
public static void InserSort(int[] array)
{
int i, j;
for (j = 1; j < array.length; j++)
{
i = j - 1;
int key = array[j];
while (i >= 0 && array[i] > key)
{
array[i + 1] = array[i];
i--;
}
array[i + 1] = key;
}
}
public static void main(String[] args)
{
int[] a = new int[] { 8, 5, 6, 4, 5, 2 };
for (int temp : a)
{
System.out.println(temp);
}
System.out.println("-------------------------------");
InsertionSort insert = new InsertionSort();
insert.InserSort(a);
for (int temp : a)
{
System.out.println(temp);
}
}
}
快速排序
快速排序采用了一种分治的策略,通常称其为分治法,其基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。快速排序算法的最差时间复杂度为O(n2),平均时间复杂度为O(n*log2n),为不稳定排序算法。
快速排序的具体过程如下:
第一步,在待排序的n个记录中任取一个记录,以该记录的排序码为准,将所有记录分成两组,第1组各记录的排序码都小于等于该排序码,第2组各记录的排序码都大于该排序码,并把该记录排在这两组中间。
第二步,采用同样的方法,对左边的组和右边的组进行排序,直到所有记录都排到相应的位置为止。
快速排序算法的Java实现代码如下:
package sortTest;
public class QuickSort
{
public static void quick(int[] a,int p,int r)
{
if(p<r)
{
int q=pation(a,p,r);
quick(a,p,q-1);
quick(a,q+1,r);
}
}
public static int pation(int[] a,int p ,int r)
{
int x=a[r];
int i=p-1;
for(int j=p;j<r;j++)
{
if(a[j]<x)
{
i++;
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
int temp=a[i+1];
a[i+1]=a[r];
a[r]=temp;
return i+1;
}
public static void main(String[] args)
{
int[] a=new int[]{4,2,4,3,7,0,2,8,9};
quick(a,0,a.length-1);
for(int i=0;i<a.length;i++)
{
System.out.println(a[i]);
}
}
}
堆排序
堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n/2-1, n/2-2, ...1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。堆排序算法的最差时间复杂度为O(n*log2n),平均时间复杂度也为O(n*log2n) ,为不稳定排序算法。
package sortTest;
public class HeapSort
{
public static int heapSize;
public static int parent(int i)
{
return (i - 1) / 2;
}
public static int left(int i)
{
return 2 * i + 1;
}
public static int right(int i)
{
return 2 * i + 2;
}
public static void maxHeapify(int[] A, int i)
{
int l = left(i);
int r = right(i);
int largest;
if ((l <= heapSize - 1) && A[l] > A[i])
largest = l;
else
largest = i;
if ((r <= heapSize - 1) && A[r] > A[largest])
largest = r;
if (largest != i)
{
int temp = A[i];
A[i] = A[largest];
A[largest] = temp;
maxHeapify(A, largest);
}
}
public static void buildMaxHeap(int[] A)
{
heapSize = A.length;
for (int i = ((A.length / 2) - 1); i >= 0; i--)
{
maxHeapify(A, i);
}
}
public static void heapSort(int[] A)
{
buildMaxHeap(A);
for (int i = (A.length / 2 - 1); i >= 0; i--)
{
if (right(i) < A.length)
System.out.println(A[i] + " " + A[left(i)] + " "
+ A[right(i)]);
else
System.out.println(A[i] + " " + A[left(i)]);
}
System.out.println("-------------------------");
for (int i = A.length - 1; i >= 1; i--)
{
int temp;
temp = A[0];
A[0] = A[i];
A[i] = temp;
heapSize--;
maxHeapify(A, 0);
}
}
public static void main(String[] args)
{
int[] A = { 5, 6, 4, 2, 8, 6, 3, 4, 7, 10 };
heapSize = A.length;
for (int value : A)
{
System.out.println(value);
}
System.out.println("-------------------------");
HeapSort heap = new HeapSort();
heap.heapSort(A);
for (int value : A)
{
System.out.println(value);
}
}
}
归并排序
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。归并排序的最差时间复杂度为O(nlog2n),平均时间复杂度为O(nlog2n)。
归并排序算法的Java实现代码如下:
package sortTest;
public class MergeSort
{
public static void merageArray(int[] array, int first, int mid, int last,
int[] temp)
{
int i, j, k;
i = first;
j = mid + 1;
k = 0;
while (i <= mid && j <= last)
{
if (array[i] <= array[j])
{
temp[k++] = array[i++];
} else
{
temp[k++] = array[j++];
}
}
while (i <= mid)
{
temp[k++] = array[i++];
}
while (j <= last)
{
temp[k++] = array[j++];
}
for (i = 0; i < k; i++)
array[first + i] = temp[i];
}
public static void merageSort(int[] a, int first, int last, int[] temp)
{
int mid;
if (first < last)
{
mid = (first + last) / 2;
merageSort(a, first, mid, temp);
merageSort(a, mid + 1, last, temp);
merageArray(a, first, mid, last, temp);
}
}
public static Boolean MergeSortFun(int[] a)
{
int[] p = new int[a.length];
merageSort(a, 0, a.length - 1, p);
return true;
}
public static void main(String[] args)
{
int[] a = new int[] { 4, 5, 2, 1, 7, 6, 3, 7, 43, 94, 3, 2, 7 };
for (int b : a)
{
System.out.println(b);
}
System.out.println("------------------------");
MergeSort merge = new MergeSort();
merge.MergeSortFun(a);
for (int b : a)
{
System.out.println(b);
}
}
}
基数排序
基数排序的思想:基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。基数排序的最差时间复杂度为O(logRB),平均时间复杂度为O(logRB),基数排序算法为稳定排序算法。
基数排序算法Java实现代码如下:
package sortTest;
import java.util.ArrayList;
import java.util.List;
public class RadixSort
{
public int[] radixSort(int[] data)
{
int max = data[0];
for (int i = 1; i < data.length; i++)
{
if (data[i] > max)
{
max = data[i];
}
}
int time = 0;
while (max > 0)
{
max /= 10;
time++;
}
List<ArrayList<Integer>> queue = new ArrayList<ArrayList<Integer>>();
for (int j = 0; j < 10; j++)
{
ArrayList<Integer> dataQueue = new ArrayList<Integer>();
queue.add(dataQueue);
}
for (int i = 0; i < time; i++)
{
for (int j = 0; j < data.length; j++)
{
int x = data[j] % (int) Math.pow(10, i + 1)
/ (int) Math.pow(10, i);
ArrayList<Integer> returnQueue = queue.get(x);
returnQueue.add(data[j]);
queue.set(x, returnQueue);
}
int count = 0;
for (int k = 0; k < 10; k++)
{
while (queue.get(k).size() > 0)
{
ArrayList<Integer> tempQueue = queue.get(k);
data[count] = tempQueue.get(0);
tempQueue.remove(0);
count++;
}
}
}
return data;
}
public static void main(String args[])
{
int a[] = { 345, 213, 137 };
int[] result = new RadixSort().radixSort(a);
for (int i = 0; i < result.length; i++)
{
System.out.println(result[i]);
}
}
}
桶排序
桶排序算法的思想:将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。桶排序的最差时间复杂度为O(n),平均时间复杂度为O(n)。
桶排序算法的Java实现代码如下:
package sortTest;
import java.util.Collections;
import java.util.LinkedList;
public class BucketSort
{
public static void bucketSort(double[] A)
{
double n = A.length;
LinkedList[] B = new LinkedList[A.length];
for (int i = 0; i < A.length; i++)
{
B[i] = new LinkedList();
}
for (int i = 0; i < A.length; i++)
{
// System.out.println((int)(n*A[i]));
B[(int) (n * A[i])].add(A[i]);
}
for (int i = 0; i < A.length; i++)
{
Collections.sort(B[i]);
}
int k = 0;
for (int i = 0; i < A.length; i++)
{
if (B[i].size() != 0)
{
for (int j = 0; j < B[i].size(); j++)
{
// System.out.println(B[i].get(j));
A[k] = (double) B[i].get(j);
k++;
}
}
// System.out.println("------------------------");
}
}
public static void main(String[] args)
{
double[] A = new double[] { 0.25, 0.36, 0.25, 0.65, 0.18, 0.48, 0.27,
0.29, 0.24, 0.75 };
bucketSort(A);
for (double temp : A)
{
System.out.println(temp);
}
}
}
计数排序
计数排序的基本思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。其最差时间复杂度O(n),平均时间复杂度为O(n),该算法为稳定排序算法。
package sortTest;
public class CountSort
{
public static void countSort(int[] A, int[] B, int k)
{
int[] C = new int[k + 1];
for (int i = 0; i < A.length; i++)
{
C[A[i]] = C[A[i]] + 1;
}
for (int temp : C)
{
System.out.println(temp);
}
System.out.println("--------------------------");
for (int i = 1; i < k + 1; i++)
{
C[i] = C[i] + C[i - 1];
}
for (int temp : C)
{
System.out.println(temp);
}
System.out.println("--------------------------");
for (int i = A.length - 1; i >= 0; i--)
{
B[C[A[i]] - 1] = A[i];
C[A[i]] = C[A[i]] - 1;
}
}
public static void main(String[] args)
{
int[] A = new int[] { 6, 2, 5, 4, 4, 3, 2, 1, 7, 8, 7, 9 };
int[] B = new int[A.length];
CountSort sort = new CountSort();
sort.countSort(A, B, 9);
for (int temp : B)
{
System.out.println(temp);
}
System.out.println("--------------------------");
}
}