排序

排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。
排序的稳定性:通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj,Ai原来在位置前,排序后Ai还是要在Aj位置前。
http://blog.csdn.net/hguisu/article/details/7776068

1.直接插入排序:(插入排序),稳定的。
思想:将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。
这个是从小到大:
public class Test {
public static void InsertSort(int[] arr){
int i,j,temp,length = arr.length;
for(i = 1;i<length;i++){
j = i;
temp = arr[i];
while(j>0 && temp < arr[j-1]){
arr[j] = arr[j-1];
j--;
}
arr[j] = temp;
}
}
}
时间复杂的是n2。


2.希尔排序:(插入排序),不稳定的。
希尔排序又叫做缩小增量排序。
希尔排序的原理:根据需求,如果你想要结果从大到小排列,它会首先将数组进行分组,然后将较大值移到前面,较小值移到后面,最后将整个数组进行插入排序,这样比起一开始就用插入排序减少了数据交换和移动的次数,
可以说希尔排序是加强版的插入排序.

public static void shellSort(int[] data) {
int j = 0;
int temp = 0;
for (int increment = data.length / 2; increment > 0; increment /= 2) {
for (int i = increment; i < data.length; i++) {
temp = data[i];
for (j = i; j >= increment; j -= increment) {
if(temp < data[j - increment]){
data[j] = data[j - increment];
}else{
break;
}
}
data[j] = temp;
}
}
}
时间复杂度nlogn
或者: public static void shellSort(int[] a){
int j=0,temp=0;
for(int increment=a.length/2;increment>0;increment/=2){
for(int i = increment;i<a.length;i++){
temp = a[i];
j = i;
while(j>0 && temp<a[j-increment]){
a[j]= a[j-increment];
j =j -increment;
}
a[j]= temp;
}
}
}
希尔排序当increment(增量等于1时),代码和直接插入排序一毛一样,看起来代码复杂了,但是因为是几乎排好序的,所以效率要搞一些。


3.简单选择排序:(选择排序)不稳定
思想:在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;
public static void sort(int[] data) {
int i,j,k,temp;
for(i=0;i<data.length;i++){
k=i;
for(j=i+1;j<data.length;j++){
if(data[k]>data[j]){
k=j;
}
}
temp = data[k];
data[k]=data[i];
data[i]=temp;
}
时间复杂的n2

4.堆排序:(选择排序)不稳定
n个元素的序列{k0,k1,...,ki,…,k(n-1)}当且仅当满足下关系时,称之为堆。
  " ki<=k2i,ki<=k2i+1;或ki>=k2i,ki>=k2i+1.(i=1,2,…,[n/2])"
堆顶为最大值或者最小值。

public static void heapSort(int[] array){
buildHeap(array);//构建堆
for(i=array.length-1;i>0;i--){
swap(array,0,i);
heapify(array,0,i);
}
}
public static void buildHeap(int[] array){
int n = array.length;//数组中元素的个数
for(int i=n/2-1;i>=0;i--)
heapify(array,i,n);
}
public static void heapify(int[] A,int idx,int max){
int left = 2*idx+1;// 左孩子的下标(如果存在的话)
int right =2*idx+2;// 左孩子的下标(如果存在的话)
int largest = 0;//寻找3个节点中最大值节点的下标
if(left<max && A[left]>A[idx])
largest = left;
else
largest = idx;
if(right<max && A[right]>A[largest])
largest = right;
if(largest!=idx){
swap(A,largest,idx);
heapify(A,largest,max);
}
}
public static void swap(int[] array,int i,int j){
int temp =0;
temp=array[i];
array[i]=array[j];
array[j]=temp;
}

时间复杂的是nlogn


5.交换排序:冒泡排序 稳定的
要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
public static void swapSort(int[] a){
for (int i = 0; i < a.length-1; i++){
for(int j = 0 ;j < a.length-i-1; j++){
if(a[j] > a[j + 1]){
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}

时间复杂度是n2

6.交换排序:快速排序 不稳定
public static void quick_sort(int a[], int low, int high){ 
if (low < high){ 
//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1 
int i = low, j = high, x = a[low]; 
while (i < j){ 
while(i < j && a[j] >= x){
j--;// 从右向左找第一个小于x的数 
}
if(i < j){
a[i++] = a[j]; 
}
while(i < j && a[i] < x){
i++;// 从左向右找第一个大于等于x的数 
}
if(i < j){
a[j--] = a[i]; 
}

a[i] = x; 
quick_sort(a, low, i - 1); // 递归调用 
quick_sort(a, i + 1, high); 

}
时间复杂度是nlogn

7.归并排序:(稳定的)
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
public static int[] sort(int[] array, int low, int high) { 
int mid = (low + high) / 2; 
if (low < high) { 
// 左边 
sort(array, low, mid); 
// 右边 
sort(array, mid + 1, high); 
// 左右归并 
merge(array, low, mid, high); 

return array; 


public static void merge(int[] array, int low, int mid, int high) { 
int[] temp = new int[high - low + 1]; 
int i = low;// 左指针 
int j = mid + 1;// 右指针 
int k = 0; 
// 把较小的数先移到新数组中 
while (i <= mid && j <= high) { 
if (array[i] < array[j]) { 
temp[k++] = array[i++]; 
} else { 
temp[k++] = array[j++]; 


// 把左边剩余的数移入数组 
while (i <= mid) { 
temp[k++] = array[i++]; 

// 把右边边剩余的数移入数组 
while (j <= high) { 
temp[k++] = array[j++]; 

// 把新数组中的数覆盖nums数组 
for (int k2 = 0; k2 < temp.length; k2++) { 
array[k2 + low] = temp[k2]; 

}

时间复杂的nlogn

8.桶排序/基数排序:稳定的
public static void basket(int a[])// data为待排序数组
{
int length = a.length;
int bask[][] = new int[10][length];
int index[] = new int[10];
int max = Integer.MIN_VALUE;
for (int i = 0; i < length; i++) {
max = max > (Integer.toString(a[i]).length()) ? max : (Integer
.toString(a[i]).length());
}
String str;
for (int i = max - 1; i >= 0; i--) {
for (int j = 0; j < length; j++) {
str = "";
if (Integer.toString(a[j]).length() < max) {
for (int k = 0; k < max
- Integer.toString(a[j]).length(); k++)
str += "0";
}
str += Integer.toString(a[j]);
bask[str.charAt(i) - '0'][index[str.charAt(i) - '0']++] = a[j];
}
int pos = 0;
for (int j = 0; j < 10; j++) {
for (int k = 0; k < index[j]; k++) {
a[pos++] = bask[j][k];
}
}
for (int x = 0; x < 10; x++)
index[x] = 0;
}
}


时间复杂度是d(n+rd) d是长度,r是关键字的基数。

原文地址:https://www.cnblogs.com/tp123/p/6602550.html