A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Struggle_168 中级黑马   /  2015-4-12 10:54  /  760 人查看  /  7 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

1、冒泡排序
冒泡排序是排序算法中最基本的一种排序方法,该方法逐次比较两个相邻数据的大小并交换位置来完成对数据排序,每次比较的结果都找出了这次比较中数据的最大项,因为是逐次比较,所以效率是O(N^2)的。
public void bubbleSort() {  
        int out,in;  
        for(out=index-1; out>1; --out) {  
            for(in=0; in<out; ++in) {  
                if(array[in]>array[in+1]) {  
                    swap(in, in+1);  
                }  
            }  
        }  
    }  
      
    public void swap(int dex1, int dex2) {  
        int temp = array[dex1];  
        array[dex1] = array[dex2];  
        array[dex2] = temp;  
    }
2、选择排序
选择排序对冒泡排序进行了优化,在每次遍历比较的过程中不进行交换,而是记录本次遍历的最小值,在遍历结束后再将最小值移到这次遍历的开始位置。这样虽然比较次数没有改变,但交换的次数大大减少,一共只需要N次交换。因为比较的次数没变,所以效率任然是O(N^2)的。

[java] view plaincopy
public void selectionSort() {  
        int out, in;  
        for(out=0; out<index-1; ++out) {  
            int temp = out;  
            for(in=out+1; in<index; ++in) {  
                if(array[in] < array[temp]) {  
                    temp = in;  
                }  
            }  
            swap(out, temp);  
        }  
    }  

3、插入排序
插入排序充分利用已排列好的数据,然后将未排序的数据插入到已排数据的队伍当中,这样每插入一个未排序数据已排队伍都将增加一个成员,最终达到排序的目的。


[java] view plaincopy
public void insertionSort() {  
        int out ,in;  
        for(out=1; out<index; ++out) {  
            int temp = array[out];  
            in = out;  
            while(in>0 && temp<array[in-1]) {  
                array[in] = array[in-1];  
                --in;  
            }  
            array[in] = temp;  
        }  
    }  

4、归并排序
归并排序是将两个有序数组合并为一个有序数组的排序,应用在一般排序上要结合二分法递归地将数组依次归并,最终得到一个大的有序数组。归并的效率是O(NlogN)的,但要额外开辟一个数组来存放临时数据,所以占用空间要大一倍。

[java] view plaincopy
public void mergeSort() {  
        int[] newArray = new int[index];  
        recMergeSort(newArray, 0, index-1);  
         
    }  
      
    private void recMergeSort(int[] data, int low, int upper) {  
        if(low == upper) {  
            return;  
        }  
        int mid = (low + upper)/2;  
        recMergeSort(data, mid+1, upper);  
        recMergeSort(data, low, mid);  
        merge(data, low, mid+1, upper);  
    }  
      
    private void merge(int[] data, int lowStart, int highStart, int upperBound) {  
        int j = 0;  
        int lowBound = lowStart;  
        int mid = highStart - 1;  
        int num = upperBound - lowStart + 1;  
         
        while(lowStart<=mid && highStart<=upperBound) {  
            if(array[lowStart] < array[highStart]) {  
                data[j++] = array[lowStart++];  
            } else {  
                data[j++] = array[highStart++];  
            }  
        }  
         
        while(lowStart<=mid) {  
            data[j++] = array[lowStart++];  
        }  
         
        while(highStart<=upperBound) {  
            data[j++] = array[highStart++];  
        }  
         
        for(j=0; j<num; j++) {  
            array[lowBound+j] = data[j];  
        }  
    }  

5、希尔排序
希尔排序是一种高级排序,它是由插入排序进化来的,插入排序是将未排的数据依次与前面已排好的数据进行比较移动,这样如果一个较小的数排在靠后的位置,那么要找到这个数的正确位置就要进行较多次移动。希尔排序改进了这种方式,它将每次比较的间隔扩大,排过一次之后数据就分阶段有序了,之后逐渐缩小这个间隔再进行排序。这样做的目的就是让数据一开始可以在一个较大的范围内进行移动,待基本有序后数据的移动量就小了很多。

[java] view plaincopy
public void shellSort() {  
        int in, out;  
        int h = 1;  
        int temp;  
        while(h < index/3) {  
            h = h*3+1;  
        }  
        while(h>0) {  
            for(out=h; out<index; ++out) {  
                temp = array[out];  
                in = out;  
                while(in>h-1 && array[in-h] > temp) {  
                    array[in] = array[in-h];  
                    in -=h;  
                }  
                array[in] = temp;  
            }  
            h = (h-1)/3;  
        }  
    }  



希尔排序中关键是对数据间隔h的选择,一个间隔序列是由Knuth提出的,即h=h*3+1,h的初始值为1,这是希尔排序中最优的间隔序列。

6、快速排序
快速排序是一种广泛使用的排序方法,效率可以达到O(NlogN),快速排序的原理是确定一个中间值pivot,将所有小于pivot的数据放在左侧,大于pivot的值放在右侧,之后再对左右两侧分别采取这种策略进行排序,直到这个过程结束。

[java] view plaincopy
private int partition(int left, int right, int pivot) {  
        int leftPtr = left;  
        int rightPtr = right-1;  
        while(true) {  
            while(array[++leftPtr] < pivot) ;  
            while(array[--rightPtr] > pivot);  
            if(leftPtr >= rightPtr) {  
                break;  
            } else {  
                swap(leftPtr, rightPtr);  
            }  
        }  
        swap(leftPtr, right-1);  
        return leftPtr;  
    }  
      
    private int median(int left, int right) {  
        int center = (left+right)/2;  
        if(array[left]>array[center]) {  
            swap(left, center);  
        }  
        if(array[left]>array[right]) {  
            swap(left, right);  
        }  
        if(array[center]>array[right]) {  
            swap(center, right);  
        }  
        swap(center, right-1);  
        return array[right-1];  
    }  
      
    private void manulSort(int left, int right) {  
        int size = right-left+1;  
        if(size <= 1) return;  
        if(size == 2) {  
            if(array[left]>array[right]) swap(left, right);  
        } else {  
            if(array[left]>array[right-1]) swap(left, right-1);  
            if(array[left]>array[right]) swap(left, right);  
            if(array[right-1]>array[right]) swap(right-1, right);  
        }  
    }  
      
    private void recQuickSort(int left, int right) {  
        int size = right-left+1;  
        if(size<=3) {  
            manulSort(left, right);  
        } else {  
            int pivot = median(left, right);  
            int partition = partition(left, right, pivot);  
            recQuickSort(left, partition-1);  
            recQuickSort(partition+1, right);  
        }  
         
    }  
      
    public void quickSort() {  
        recQuickSort(0, index-1);  
    }  
快速排序的关键是确定中间值pivot,如果中间值选取的不好,会使快速排序的效率降到O(N^2)。上面的例子采用了三选一的策略来确定中间值,即在要排序的数据中选择左端、中间和右端三个数据后比较取中间值;还有在数据量较小时,比如小于三个则直接手动排序。

7 个回复

倒序浏览
后四种排序方法,在视频中都没有讲解过,是自学的吗!楼主很强啊
回复 使用道具 举报
数据结构里面的知识  顶一下
回复 使用道具 举报
佩服啊,后两种没有看懂
回复 使用道具 举报
好像不需要都了解吧。。。。?
回复 使用道具 举报
总结的很好。赞。
回复 使用道具 举报
挺好,总结的不错
回复 使用道具 举报
总结的很好啊
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马