排序算法

Posted 刘宛秋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法相关的知识,希望对你有一定的参考价值。

最近看了《大话数据结构》简单的把上面的算法总结一下:

简单算法:冒泡排序,简单选择排序,直接插入排序
改进算法:希尔排序,堆排序,归并排序,快速排序
插入排序:直接插入排序和希尔排序
交换排序:冒泡排序和快速排序
选择排序:简单选择排序和堆排序

冒泡排序:

  思想:两两比较相邻记录的关键字,大的放后面。这样,每一轮下来,最大的被放在了最后。

Java代码:
public int[] sort(int[] a){
    int temp = 0;
    for (int i = a.length - 1; i > 0; --i){
        for (int j = 0; j < i; ++j){
            if (a[j + 1] < a[j]){
                temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
    return a;
}

  

简单选择排序:

  简单选择排序性能上略优于冒泡排序:

       简单选择排序是从第一个元素开始(i=0),依次与其后的元素进行比较,找出最小元素的下标(j),放在下标是i的位置。

Java代码为:
public int[] selectsort(int[] array){
    int min,temp;//最小数标记
    int len = array.Length;
    for(int i=0; i<len; i++){
        min=i;
        for(int j=i+1; j<len; j++){
		if(array[min]>array[j]){
		    min=j;
		}
	}
	tmp=array[i];
	array[i]=array[min];
	array[min]=tmp;
    }
    return array;
}

  

直接插入排序:

  直接插入排序是将一个记录插入到已经排好序的有序表中。

  第一个元素不管了,相当于直接放进去的,然后后面的元素依次与前面的元素进行比较。所以下标是从1开始的。

Java代码如下:
private int[] insertSort(int[] arr){
	if(arr == null || arr.length < 2){
	    return arr;
	}
	for(int i=1;i<arr.length;i++){
		for(int j=i;j>0;j--){
			if(arr[j]<arr[j-1]){
				int temp=arr[j];
				arr[j]=arr[j-1];
				arr[j-1]=temp;
			}else{
			  //接下来是无用功
			  break;
			}
		}
	}
	return arr;
}

希尔排序:

  希尔排序是插入排序的一种

  一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

public int[] ShellSort(int[] a){
    int len=a.length;
    while(true){
        len=len/2;
        for(int x=0;x<len;x++){
            for(int i=x+len;i<a.length;i=i+len){
                int temp=a[i];
                int j;
                for(j=i-len;j>=0 && a[j]>temp;j=j-len){
			//此for循环实现排序,差不多相当于插入排序
			//与其前元素比较,当前元素比比较的元素小,其它元素后移
			//给当前元素让位置
                      a[j+len]=a[j]; 
                }
		//此元素比它前面的元素大,把空出来的位置放此元素
                a[j+len]=temp;
            }
        }
        if(len==1){
            break;
        }
    }
    return a;
} 

  

快速排序:

  关键字靠近谁,保护谁(原理自己百度一下吧,死记),每一轮选出一个关键字,两个指针low和high,先选数组中的第一个元素作为关键字

public void sort(int arr[],int low,int high){
	int l=low;
	int h=high;
	int povit=arr[low];
	while(l<h){
		while(l<h&&arr[h]>=povit)
			h--;
		if(l<h){
			int temp=arr[h];
			arr[h]=arr[l];
			arr[l]=temp;
			l++;
		} 
	      while(l<h&&arr[l]<=povit){
			l++;
		}		 
		if(l<h){
			int temp=arr[h];
			arr[h]=arr[l];
			arr[l]=temp;
			h--;
		}
	}
	if(l>low)
		sort(arr,low,l-1);
	if(h<high)
		sort(arr,l+1,high);
	return arr;
}

 

堆排序:

  大顶堆:从最后一个非叶子节点开始,往前逐步调整,让每个双亲都大于子女,至到根结点为止。每次找到最大结点后放置最后一个位置。然后再调整出最大的放在倒数第二个位置。

  创建堆的时候就一个一个元素向二叉树上添加,不用管排序情况。序列表中前一半的程序就是此二叉树的非叶子节点。

//堆排序
public class HeapSort {  
        public static void main(String[] args) {  
            int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3 };  
            heapSort(array);  
        }  
  
        public static void heapSort(int[] array) {  
            if (array == null || array.length <= 1) {  
                return;  
            }  
            buildMaxHeap(array);  
            for (int i = array.length - 1; i >= 1; i--) {  
                exchangeElements(array, 0, i);  
                maxHeap(array, i, 0);  
            }  
        }  
  
        private static void buildMaxHeap(int[] array) {  
            if (array == null || array.length <= 1) {  
                return;  
            }  
            //[0...half]是非叶子节点
            int half = array.length / 2;  
            for (int i = half; i >= 0; i--) {
                //把当前树的数组,数组长度,子树根的位置传过去  
                maxHeap(array, array.length, i);  
            }  
        }  
  
        private static void maxHeap(int[] array, int heapSize, int index) {  
            int left = index * 2 + 1;  
            int right = index * 2 + 2;  
            //树根的位置记录下来
            int largest = index;  
            //左子树存在并且左子树值比根大
            if (left < heapSize && array[left] > array[index]) {  
                //标记出大的位置
                largest = left;  
            }  
            //右子树存在,并且右子树的值比之前找出的最大的值大
            if (right < heapSize && array[right] > array[largest]) {  
                largest = right;  
            }  
  
            if (index != largest) {
                //跟下标和找出的最大值下标不一样,交换这两个值  
                exchangeElements(array, index, largest);  
                //替换后元素的堆,让它重新平衡
                maxHeap(array, heapSize, largest);  
            }  
        } 
        //交换两个元素的值
        public static void exchangeElements(int[] array, int index1, int index2) {  
            int temp = array[index1];  
            array[index1] = array[index2];  
            array[index2] = temp;  
        }   
}  

  

 

  

以上是关于排序算法的主要内容,如果未能解决你的问题,请参考以下文章

算法排序之堆排序

快速排序-递归实现

从搜索文档中查找最小片段的算法?

在第6731次释放指针后双重免费或损坏

TimSort算法分析

以下代码片段的算法复杂度