排序算法

一、简单选择排序

        设所排序序列的记录个数为n。i取1,2,...,n-1,从所有n-i+1个记录中找出排序码最小的记录,与第i个记录交换。执行n-1趟后就完成了记录序列的排序。

        最好时间复杂度:O(n^2), 平均时间复杂度:O(n^2), 最坏时间复杂度:O(n^2)     辅助存储:O(1)    不稳定

public class SelectionSort {
    public int[] selectionSort(int[] A, int n) {
        int position = 0;
        for(int i=0;i<n;i++){
            int minStemp=java.lang.Integer.MAX_VALUE;
            for(int j=i;j<n;j++){
                if(A[j]<minStemp){
                    minStemp = A[j];
                    position = j;
                }
            }
            int temp = A[i];
            A[i] = minStemp;
            A[position] = temp;
        }
        return A;
    }
}

二、直接插入排序

        每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。

        最好时间复杂度:O(n), 平均时间复杂度:O(n^2), 最坏时间复杂度:O(n^2)    辅助存储:O(1)    稳定

public class InsertionSort {
    public int[] insertionSort(int[] A, int n) {
        int j=0;
        for(int i=0;i<n;i++){
            int temp = A[i];
            for(j=i;j>0&&A[j-1]>temp;j--){
                A[j]=A[j-1];
            }
            A[j]=temp;
        }
        return A;
    }
}

三、冒泡排序

        比较相邻的元素,如果第一个比第二个大,就交换他们两个。对每一对相邻的元素作同样的工作,从开始第一对到结尾的最后一对,最后的元素应该是最大的数。

        最好时间复杂度:O(n), 平均时间复杂度:O(n^2), 最坏时间复杂度:O(n^2)    辅助存储:O(1)    稳定

public class BubbleSort {
    public int[] bubbleSort(int[] A, int n) {
        int temp;
        for(int i=0;i<n-1;i++){
            for(int j=0;j<n-i-1;j++){
                if(A[j]>A[j+1]){
                    temp = A[j+1];
                    A[j+1] = A[j];
                    A[j] = temp;
                }
            }
        }
        return A;
    }
}

四、希尔排序

        它是直接插入排序的一种,也称缩小增量排序,是直接插入排序算法的一种更高效地改进版本。

        先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组,所有距离为d1的倍数的记录放在同一个组中。现在各组内进行直接插入排序;然后,取第二个增量d2<d1,重复上述的分组和排序,直至所取的增量dt=1,即所有记录放在同一组中进行直接插入排序为止。

        最好时间复杂度:O(n), 平均时间复杂度:O(n*logn), 最坏时间复杂度:O(n*s) s为所选分组    辅助存储:O(1)    不稳定

public class ShellSort {
    public int[] shellSort(int[] A, int n) {
         
        if(A==null || n<2)
            return A;
         
        int feet = n/2;
        int index = 0;
        while(feet > 0){
            for(int i=feet; i<n; i++){
                index = i;
                while(index >= feet){
                    if(A[index-feet] > A[index]){
                        swap(A,index-feet,index);
                        index-=feet;
                    }else{
                        break;
                    }
                }
            }
            feet = feet/2;
        }
        return A;
    }
     
    void swap(int[] A,int m,int n){
        int temp = A[m];
        A[m] = A[n];
        A[n] = temp;
    }
}

五、快速排序

        它是对冒泡排序的一种改进。

        基本思想:通过一趟排序将要排序的部分分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按照此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

        最好时间复杂度:O(n*logn), 平均时间复杂度:O(n*logn), 最坏时间复杂度:O(n^2)     辅助存储:O(logn)    不稳定

public class QuickSort {
   public static int[] quickSort(int[] A, int n) {
        quick(A, 0, n - 1);
        return A;
    }
 
    private static int[] quick(int[] A, int low, int high) {
        if (low < high) {
            int mid = sort(A, low, high);
            quick(A, low, mid-1);
            quick(A, mid + 1, high);
        }
        return A;
    }
 
    private static int sort(int[] A, int low, int high) {
        int key = A[low];
        int i = low;
        int j = high;
        if (low < high) {
            while (i < j) {
                while (i < j && key <= A[j]) {
                    j--;
                }
                if (i < j) {
                    A[i] = A[j];
                }
                while (i < j && A[i] <= key) {
                    i++;
                }
                if (i < j) {
                    A[j] = A[i];
                }
            }
            A[i] = key;
        }
        return i;
    }
}

六、堆排序

        用大根堆排序的基本思想:

        1)先将初始文件R[1,...,n]建成一个大根堆,此堆为初始的无序区。

        2)再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1,...,n-1]和有序区R[n],且满足R[1,...,n-1].keys<=R[n].key。

        3)由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1,...,n-1]调整为堆。然后再次将R[1,...,n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1,...,n-2]和有序区R[n-1,n],且仍满足关系R[1,...,n-2].keys<=R[n-1,n].keys。同样要将R[1,...,n-2]调整为堆。

        ......

        直到无序区只有一个元素位置。

        最好时间复杂度:O(n*logn), 平均时间复杂度:O(n*logn), 最坏时间复杂度:O(n*logn)     辅助存储:O(1)    不稳定

public class HeapSort {
    public int[] heapSort(int[] A, int n) {
        for(int i=n/2; i>=0; i--){
            heapAdjust(A,i,n);
        }
         
        for(int i=n-1;i>0;i--){
            swap(A,0,i);
            heapAdjust(A,0,i);
        }
        return A;
    }
     
    public void heapAdjust(int[] A,int index,int length){
        int childLeft;
        int temp = A[index];
        for( ;index*2+1 < length;index = childLeft){
            childLeft = index*2+1;
            if(childLeft !=length-1 && A[childLeft] < A[childLeft+1]){
                 childLeft++;
            }
            if(temp > A[childLeft]){
                break;
                 
            }                
            else {
                A[index] = A[childLeft];
                index = childLeft;
            }           
        }
         A[index] = temp;
         
    }
     
    public static void  swap(int[] A,int m,int n){
        int temp = A[m];
        A[m] = A[n];
        A[n] = temp;
    }
}

七、归并排序

        归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,成为二路归并。

        归并排序的算法通常用递归实现,先把待排区间[s,t]以中点二分,接着把左边自区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

        最好时间复杂度:O(n*logn), 平均时间复杂度:O(n*logn), 最坏时间复杂度:O(n*logn)     辅助存储:O(n)    稳定

public class MergeSort {
    public int[] mergeSort(int[] A, int n) {
        sort(A,0,n-1);
        return A;
    }
    public void sort(int[] data,int left,int right){
        if(left<right){
            int middle = (left+right)/2;
            sort(data,left,middle);
            sort(data,middle+1,right);
            merge(data,left,middle,right);
        }
    }
    public void merge(int[] data,int left,int middle,int right){
        int[] tempArr = new int [right-left+1];
        int leftIndex = left;
        int rightIndex = middle+1;
        int tempIndex = 0;
        while(leftIndex<=middle && rightIndex<=right){
            if(data[leftIndex]<=data[rightIndex]){
                tempArr[tempIndex++] = data[leftIndex++];
            } else {
                tempArr[tempIndex++] = data[rightIndex++];
            }
        }
        while(leftIndex<=middle){
            tempArr[tempIndex++] = data[leftIndex++];
        }
        while(rightIndex<=right){
            tempArr[tempIndex++] = data[rightIndex++];
        }
        int temp = 0;
        while((temp+left)<=right){
            data[left+temp] = tempArr[temp];
            temp++;
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值