• 排序算法


    1.冒泡排序

       思想:同过比较相邻两个的值,一趟排序后将最大值max放在最右端,再经过一趟排序将次大值排在max左边,依此数次排序后得到一个有序数组。

       算法平均复杂度:O(n2)。

       是否稳定:稳定。

    public class BubbleSort {
        public static void sort(int []arr){
            for(int i=0;i<arr.length-1;i++){//外部循环控制排序趟数
                for(int j = 0;j<arr.length-1-i;j++){//内部循环决定每一趟比较次数
                    if(arr[j]>arr[j+1]){ //升序
                        int temp = arr[j];
                        arr[j] = arr[j+1];
                        arr[j+1] = temp; 
                    }
                }
            }
        }
        public static void main(String[] args) {
              int[] arr = {8,2,1,6,7,3,4,0};
              sort(arr);
              System.out.println(Arrays.toString(arr));
        }
    }

    2.快速排序

    思想:采用分治的思想。首先选取一个基准元素,经过一趟排序之后,将比基准元素小的放在其左边,比基准元素大的放在其右边,将数组分成两部分。对于左边的部分,再选取一个基准元素将棋再分为两部分,右边同样如此。如此,多躺排序之后得到一个有序数列。

    算法平均复杂度:O(NlogN)

    是否稳定:不稳定

    public class QuickSort {
    
        public static void main(String[] args) {
            int a[]={1,4,3,8,5,9,6};
            QuickSort(a, 0, 6);
            for (int i : a) {
                System.out.println(i);
            }
        }
        public static void QuickSort(int a[],int p,int r){
            if(p<r){
                int q = Partition(a, p, r);
                QuickSort(a, p, q-1);
                QuickSort(a, q+1, r);
            }
        }
        public static int Partition(int a[],int p,int r){
           int i = p,j =r+1;
           int x = a[p];
            while(true){
                while(a[++i]<x &&i<r );
                while(a[--j]>x);
                if(i>=j) break;
                Swap(a,i,j);
            }
            a[p] = a[j];
            a[j] = x;   
            return j;
        }
        
        public static void Swap(int a[],int i, int j){
            int temp; 
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    }

    3.堆排序

     思想:将数组元素构造成大顶推或小顶堆,然后将堆定元素与堆尾元素交换,再重构大顶堆,将堆顶元素与堆尾交换。重复数次后形成有序数列。

    算法平均复杂度:O(nlogn)

    是否稳定:不稳定。

            

    public class Heapsort {
        public static void main(String []args){
            int []arr = {0,8,7,6,9,10,3,2,1};
            sort(arr);
            System.out.println(Arrays.toString(arr));
        }
        public static void sort(int []arr){
            //1.构建大顶堆
            for(int i=arr.length/2-1;i>=0;i--){
                //从第一个非叶子结点从下至上,从右至左调整结构
                adjustHeap(arr,i,arr.length);
            }
            //2.调整堆结构+交换堆顶元素与末尾元素
            for(int j=arr.length-1;j>0;j--){
                swap(arr,0,j);//将堆顶元素与末尾元素进行交换
                adjustHeap(arr,0,j);//重新对堆进行调整
            }
        }
        public static void adjustHeap(int []arr,int i,int length){
            int temp = arr[i];//先取出当前元素i
            for(int k=i*2+1;k<length;k=k*2+1){//从i结点的左子结点开始,也就是2i+1处开始
                if(k+1<length && arr[k]<arr[k+1]){//如果左子结点小于右子结点,k指向右子结点
                    k++;
                }
                if(arr[k] >temp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
                    arr[i] = arr[k];
                    i = k;
                }else{
                    break;
                }
                arr[i] = temp;//将temp值放到最终的位置
            }
        }
    //从最后一个父节点出发,找到子节点,比较子节点大小,将其与子节点大的进行交换。依次重复,直到构建成大顶堆后完毕。
    public static void swap(int []arr,int a ,int b){ int temp=arr[a]; arr[a] = arr[b]; arr[b] = temp; } }

    4.插入排序

    思想:从待排序的序列中选择一个元素,将其插入到已排序好的元素序列中 ,重复上述步骤直到待排序序列中没有元素为止。

    复杂度:O(n2)

    是否稳定:稳定

    
    
    public class InsertSort {
    //直接插入排序
    //a为待排序数组,n代表数组长度
    public void insertSort(int a[],int n){
    for(int i = 1;i<n;i++){
    for(int j = 0;j<i;j++){
    if(a[j]>a[i]){//升序排序
    //交换 a[j] a[i]
    a[j] = a[i] +a[j];
    a[i] = a[j] - a[i];
    a[j] = a[j] - a[i];
    }
    }
    }
    }

    public static void main(String[] args) {
    InsertSort insertSort = new InsertSort();
    int a[] = {3,4,1,2,6,7,9,8};
    insertSort.insertSort(a,a.length);
    System.out.println(Arrays.toString(a));
    }
    }
     

     5.选择排序

    思想:在未排序的序列中选择最小的元素,放在已排序的队列首部,然后再从未排序的序列中选择最小的放到以排序的队列中去。以此重复,知道未排序的序列没有元素为止。

    平均复杂度:O(n2)

    是否稳定:不稳定

    function selectionSort(arr) {
        var len = arr.length;
        var minIndex, temp;
        for (var i = 0; i < len - 1; i++) {
            minIndex = i;                         //每次都从已排序序列的末尾后一位开始
            for (var j = i + 1; j < len; j++) {
                if (arr[j] < arr[minIndex]) {     //寻找最小的数
                    minIndex = j;                 //将最小数的索引保存
                }
            }
           //放到已排序序列的末尾(即交换),该操作很有可能把稳定性打乱,所以选择排序是不稳定的排序算法
            temp = arr[i];  
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
        return arr;
    }

     6.归并排序

    思想:归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

    public class MergeSort {
        public static void main(String []args){
            int []arr = {9,8,7,6,5,4,3,2,1};
            sort(arr);
            System.out.println(Arrays.toString(arr));
        }
        public static void sort(int []arr){
            int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
            sort(arr,0,arr.length-1,temp);
        }
        private static void sort(int[] arr,int left,int right,int []temp){
            if(left<right){
                int mid = (left+right)/2;
                sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
                sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
                merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
            }
        }
        private static void merge(int[] arr,int left,int mid,int right,int[] temp){
            int i = left;//左序列指针
            int j = mid+1;//右序列指针
            int t = 0;//临时数组指针
            while (i<=mid && j<=right){
                if(arr[i]<=arr[j]){
                    temp[t++] = arr[i++];
                }else {
                    temp[t++] = arr[j++];
                }
            }
            while(i<=mid){//将左边剩余元素填充进temp中
                temp[t++] = arr[i++];
            }
            while(j<=right){//将右序列剩余元素填充进temp中
                temp[t++] = arr[j++];
            }
            t = 0;
            //将temp中的元素全部拷贝到原数组中
            while(left <= right){
                arr[left++] = temp[t++];
            }
        }
    }

    总结

  • 相关阅读:
    谷歌浏览器默认字体最小12px的解决方案
    字符编码笔记:ASCII,Unicode和UTF8 (转)
    关于URL编码(转)
    .net 应用程序域的影子复制
    .net动态加载程序集和影子复制(Dynamic Load Assembly and Shadow Copy)
    关于.net影子复制的问题
    来得有点晚,不过博客不分先后 :)
    App Domains and dynamic loading
    AppDomain and Shadow Copy
    Delphi实现软件自动更新源代码
  • 原文地址:https://www.cnblogs.com/menbo/p/9717849.html
Copyright © 2020-2023  润新知