zoukankan      html  css  js  c++  java
  • 各路排序神仙理解以及Java实现

    啊啊啊啊啊啊!大话数据结构终于看到了排序这一章章啦,然而各路排序神仙,真的是看懂了!仅仅是看懂了,所以打算用两天的时间比几个常见的算法写一遍啦,加深一下印象。嘤嘤嘤

    参考博客
    十大经典排序算法(动图演示

    冒泡排序

    这个算法我记得是上C语言就接触了,他的思想是,遇到逆序对,就进行交换啊,就这样慢慢的第n个有序,第n-1个有序.......全部有序。 关键点在于如果一次遍历,都没有交换操作的话,那说明已经有序啦,跳出循环。排序完成。

    package com.it592.sort;
    
    public class BubbleSort extends Sort {
        @Override
        public void sort(int nums[]) {
            int len = nums.length;
            for (int i = 0; i < len; i++){
                boolean flag = true;
                for (int j = 0; j < len - i -1; j++){
                    if(nums[j] > nums[j+1]){ // 判断是否逆序,如果逆序,说明还没找到正确的位置,继续后移
                        nums[j] += nums[j+1];
                        nums[j+1] = nums[j] - nums[j+1];
                        nums[j] -= nums[j+1];
                        flag = false;
                    }
                }
                if (flag)
                    break;
            }
        }
    }
    

    选择排序

    选择排序,按照大话数据结构的话说,其实和冒泡排序差不多,但是这两个算法的侧重点不同,冒泡排序每次都进行交换操作,其实有很多交换是没有必要的,毕竟交换也要费点时,选择排序他只是观察,找到适合某个位置的点,然后再进行交换,这就好比炒股票,冒泡排序是看到每次涨了之后,都卖出去,然后降了再买点回来,而选择排序是看到最高点,再抛售,这就省去了中间交易的开销,也就是冒泡排序时候交换的时候开销。

    package com.it592.sort;
    
    public class SelectSort extends Sort {
        @Override
        public void sort(int[] nums) {
            for (int i = 0; i < nums.length - 1; i++){
                int key = i;
                for (int j = i + 1; j < nums.length; j++){ //找到适合i的值。
                        if (nums[key] > nums[j])
                            key = j;
                }
                if(key != i){
                    nums[i] += nums[key]; //让i变为有序的
                    nums[key] = nums[i] - nums[key];
                    nums[i] -= nums[key];
                }
            }
        }
    }
    

    插入排序

    插入排序的思想是,假设序列已经有序了,那么我们只需要把当前元素插入到正确的位置即可。首先,对于第一个元素,因为只有一个元素,所以他是有序的,对于第二个元素,则与第一个元素进行判断,如果比第一个元素小,则插到第一个元素之前,第一个元素后移;对于第三个元素,则和前两个元素进行比较,找到合适的位置,插入即可。依次类推,最终有序。

    package com.it592.sort;
    
    public class InsertSort extends Sort {
        @Override
        public void sort(int[] nums) {
            int len = nums.length;
            for(int i = 0; i < len -1 ; i++){
                int tmp = nums[i+1];
                int j = i+1;
                for(; j > 0; j--){
                    if(nums[j-1] > tmp){
                        nums[j] = nums[j-1];
                    }else
                        break;
                }
                nums[j] = tmp;
            }
        }
    }
    

    希尔排序

    在插入排序中,由于要把某个元素放到合适的位置上,这样可能就会导致其他元素偏离他本来的位置很远,希尔排序是对插入排序的一种改进,他可以将小的元素放到前面去,而大的元素集中在尾部。方法是,将数组进行分组,例如[2,5,1,4,5,55,11,1,15,19,2,33,55,8],我们设置space=3,那么则[2,11,19,55],[5,5,1,2,8],[1,55,15,33]为三个分组,使用插入排序对他们进行排序后,就会得到以下结果[2,1,1,11,2,15,19,5,33,55,5,55,8],通过这样一轮排序之后,就会发现小的部分相对集中在前面,而大数则集中在后面。最终循环完毕,有序

    package com.it592.sort;
    
    public class ShellSort extends Sort {
        @Override
        public void sort(int[] nums) {
            int gap = nums.length / 3 + 1;
    
            while (true){
                    for (int i = 0; i < nums.length - gap; i += gap){
                        int tmp = nums[i+gap];
                        int j = i + gap;
                        for (; j > 0; j -= gap){
                            if(nums[j-gap] > tmp)
                                nums[j] = nums[j-gap];
                            else
                                break;
                        }
                        nums[j] = tmp;
                    }
                    if (gap == 1) // gap 等于 1的时候,说明进行了一次正常的插入排序,over,推出。
                        break;
                    gap = gap / 3 + 1;
    
            }
        }
    }
    

    归并排序

    归并排序,其实就是相当于划分成子问题,然后再合并起来,这玩意难点不在思路,递归实现贼方便,但是嘤嘤嘤,非递归就不那么容易啦。具体代码解释吧

    package com.it592.sort;
    
    public class MergeSort extends Sort {
        @Override
        public void sort(int[] nums) {
            mergeSort(nums);
        }
    
        private void mergeSort(int[] nums){
            /*
                主要包含两个部分,第一个分组,第二个是组内排序并合并
             */
            int space = 2; //space 用来设置当前划分的子问题的大小*2,
            while (space <= nums.length){
                int i = 0;
                while (i + space <= nums.length){
                        merge(nums,i,i + space / 2, i + space ); // 将子问题的解合并
                        i += space; //更新子问题的坐标,向后移动,继续解决其他子问题
                }
                if ((i + space / 2 - 1) < nums.length) //如果有剩余的没办法进行排序,那此次进行排序。
                    merge(nums, i, i+space/2, nums.length);
                space *= 2;
            }
            merge(nums, 0, space / 2, nums.length); //从头到尾,合并一次。
        }
    
        private void merge(int nums[],int left, int center, int right){
            int temp[] = new int[right - left + 1];
            int cnt = 0;
            int i = left;
            int j = center;
            while (i < center && j < right){
                if (nums[i] > nums[j]){
                    temp[cnt++] = nums[j++];
                }else
                    temp[cnt++] = nums[i++];
            }
            while (i < center){
                temp[cnt++] = nums[i++];
            }
            while (j < right){
                temp[cnt++] = nums[j++];
            }
            cnt = 0;
            for (i = left; i < right; i++){
                nums[i] = temp[cnt++];
            }
        }
    }
    
    

    快速排序

    快速排序的思想主要也是分治,主要是找到一个节点,把他放到合适的位置上,使左边的都比节点小(大),右边都比节点大(小)。他最关键的点就在找这个节点的合适位置,找法就是从右到左找到比节点小的点,交换,然后再从左往右找到合适的点,交换,直接i和j相等.具体看参考。
    白话经典算法系列之六 快速排序 快速搞定

    package com.it592.sort;
    
    public class QuickSort extends Sort {
        @Override
        public void sort(int[] nums) {
                quick_sort(nums,0,nums.length-1);
        }
    
        private void quick_sort(int[] nums, int left, int right){
            int i = left;
            int j = right;
            if(left < right){
                int tmp = nums[i];
                while (i < j){
                    while (i < j && nums[j] > tmp)
                        j--; // 找到第一个小数
                    if(i < j)
                        nums[i++] = nums[j];
                    while (i < j && nums[i] < tmp)
                        i++;
                    if(i < j)
                        nums[j--] =  nums[i];
                }
                nums[i] = tmp;
                quick_sort(nums,left,i-1);
                quick_sort(nums,i+1,right);
            }
        }
    }
    
    
  • 相关阅读:
    context-annotation
    bean-annotation
    K-means算法
    基于概率的分类-贝叶斯分类
    Application
    ConfigurableApplicationContext
    相关性分析
    方差分析
    Java 大写金额转换成数字
    linux 遍历文件添加index
  • 原文地址:https://www.cnblogs.com/xmxj0707/p/9764271.html
Copyright © 2011-2022 走看看