排序算法二 归并排序和快速排序

这篇具有很好参考价值的文章主要介绍了排序算法二 归并排序和快速排序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

归并排序

快速排序

1 挖坑法​编辑

2 Hoare法

快排的优化

快排的非递归方法

七大排序算法复杂度及稳定性分析


归并排序

归并排序是建立在归并操作上的一种有效的排序算法,将以有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,在使子序列段间有序.若将两个有序的序列合并成一个有序表,成为二路归并.

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

归并排序的递归写法:

1:  首先建行区间一分为二,分裂点 : mid = ( left + right ) / 2;

2:  递归的对两个子区间array[left..mid] 和 array[mid+1 ... right]进行归并排序.递归的终止条件是子区间的长度为1.

3:  将两个子区间归并为一个有序的空间.但我们归并右树的时候不是从原来数组的0下标开始,所以我们在归并的时候要加上他原来数组所在的下标 即 array[i + start] = tmp[i];

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

代码:

public void mergeSort(int[] array) {
        sort(array,0,array.length-1)
    }
    private void sort(int[] array,int left,int right) {
        if(left >= right) {
            return;
        }
        int mid = (left + right) / 2;
        sort(array,left,mid);
        sort(array,mid+1,right);
        //合并
        merge(array,left,right,mid);
    }
    //合并
    private void merge(int[] array,int start,int end,int mid) {
        int s1 = start;
        int s2 = mid + 1;
        int[] tmp = new int[end - start + 1];
        int k = 0;
        while(s1 <= mid && s2 <= end) {
            if(array[s1] <= array[s2]) {
                tmp[k++] = array[s1++];
            } else {
                tmp[k++] = array[s2++];
            }
        }
        while(s1 <= mid) {
            tmp[k++] = array[s1++]
        }
        while(s2 <= end) {
            tmp[k++] = array[s2++];
        }
        for (int i = 0; i < tmp.length; i++) {
            array[i + start] = tmp[i];
        }
    }
}

归并排序的非递归写法:

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

首先将一组序列的每个元素看做一个单独的序列,进行比较之后排好序,然后在每两个一组进行比较,直到组数和和序列的个数相同,序列就拍好序了

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

归并排序的特性总结 :

归并排序的时间复杂度是O(N* log₂N),空间复杂度是O(N),稳定性是稳定的排序

快速排序

快速排序是一种二叉树结构的交换排序方法,其基本思想是任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序结合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后按照左右子序列重复该过程,直到所有元素排列在相应位置上位置.

动图展示

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

快速排序有很多方法,在这里我主要讲两种方法

1 挖坑法

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

首先我们在这个排序序列中随便找一个基准值,通常为了方便,以第一个数作为基准值,然后我们从后往前找比基准值小的元素,找到后把这个元素放到基准值的位置

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

然后我们从前往后找比基准值大的元素,然后把这个元素放到坑里.会出现一个新的坑

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

然后重复上面操作直到将left和right相遇,我们把基准值放到坑位里面.

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

代码展示

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

大家想想,我们在内层while循环中, <= 和 >=能换成> 和 < 吗?

答案是不可以的 

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

当最后一个元素和第一个元素大小相等的时候,如果取 > 和 < 的情况下,是要进行和基准值交换的,当从后往前走完后,从前往后走,又满足交换条件,这样就成了死循环.

2 Hoare法

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

同样的方法我们先找一个基准,然后从后往前找比基准值小的,找到后从前往后找比基准值大的,找到后交换两个的位置

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言然后重复上面的操作直到lleft和right相遇

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

然后让array[left] 和基准值交换位置,我们发现比基准值小的都在基准值的左边,比基准值大的都在基准值的右边

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

根据两种方法的比较,我们会发现两种序列的顺序是不一样的,

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

当我们左边找基准值的时候,为什么要从右边先走呢?

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

以Hoare法为例,当我们先从左边走,在走右边,交换后right位置的值一定比基准值大,当Left和right相遇的时候,将左边的值和基准值交换,较大值就排到前面去了,就不满足基准值左边的都比基准值小的性质了

快速排序的基本特性

快速排序是一种二叉树结构的交换排序方法.

时间复杂度: 最好的情况  O(N * log₂ N)  ,最坏的情况给的序列本来就有序,在递归的时候只会是一棵单支树,树的高度就为N,时间复杂度为O(N ^ 2),

空间复杂度:  最好情况: O(log₂ N), 最坏情况 : O(N)

稳定性: 不稳定的

快速排序需要再系统内部用一个栈来实现递归,每层递归调用时的指针和参数均需要用栈来存放,快速排序的递归过程可以用一颗二叉树来表示,当数据量较大时,在最坏的情况时,可能会发生栈溢出异常,所以我们要对快速排序进行优化.

快排的优化

三数取中法

在一组排序序列中,我们选取三个数,分别是第一个数,中间位置的数和最后一个数,在这三个数中选取中间大的数作为基准数. 这样就不会出现单支树的情况. 

如何在三个数中找中间大的数呢?

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言

快速排序是一种二叉树结构的交换排序方法.在二叉树中,层数越多,下面的节点数就越多,也趋于有序,在后面两层可以直接使用直接插入法进行排序,减少递归的次数.

 public void quickSort(int[] array) {
        quick(array,0,array.length-1);
    }

    private void quick(int[]array,int start, int end) {
        if(start >= end) {
            return ;
         }
        if(end - start + 1 <= 14) {
            //插入排序
            insertSoft2(array,start,end);
            return;
        }
        int index = midThree(array,start,end);
        swap(array,index,start);

        int piovt = partition(array,start,end);
        quick(array,start,piovt-1);
        quick(array,piovt+1,end);
    }
    private int partition(int[] array,int left,int right) {
        int tmp = array[left];
        int i = left;
        while(left < right) {
            while(left < right && array[right] >= tmp) {
                right--;
            }
            array[left] = array[right];
            while(left < right && array[left] <= tmp) {
                left++;
            }
            swap(array,left,right);
        }
        swap(array,left,i);
        return left;
    }
    public static void insertSoft2(int[] array,int left,int right) {
        for(int i = left+1; i <= right;i++) {
            int tmp = array[i];
            int j = i -1;
            for(j =i-1; j >= left ;j--) {
                if(array[j] > tmp) {
                    array[j+1] = array[j];
                } else {
                    array[j+1] = tmp;
                    break;
                }
            }
            array[j+1] = tmp;
        }
    }

快排的非递归方法

在第一次找到基准值之后,我们将基准值左边和右边的下标放到栈中,排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言第一次弹出栈顶元素给到right在弹出栈顶元素给left.重新找基准值,找到后把基准值左右两边重新入栈,重复上述操作但当基准值左右两边只有一个元素的时候,就不需要再入栈,此时已经是有序的了,把最开始的基准值右边的排完后,排基准值左边的.,直到栈为空的时候,排完序.

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言第一次弹出栈顶元素给到right在弹出栈顶元素给left.重新找基准值,找到后把基准值左右两边重新入栈,重复上述操作但当栈为空的时候排序完成

public void quickSort(int[] array) {
    Deque<Integer> stack = new LinkedList<>();
    int left = 0;
    int right = array.length - 1;
    int pivot = partition(array,left,right);
    
    if(pivot > left + 1) {
        stack.push(left);
        stack.push(pivot -1);
        
    }
    if(pivot < right- 1) {
        stack.push(pivot+ 1);
        stack.push(right);
    }
    while(!stack.isEmpty()) {
        right = stack.pop();
        left = stack.pop();
        pivot = partition(array,left,right);

        if(pivot > left + 1) {
            stack.push(left);
            stack.push(pivot -1);
        }
        if(pivot < right- 1) {
            stack.push(pivot+ 1);
            stack.push(right);
        }
    }
}
private int partition(int[] array,int left,int right) {
    int tmp = array[left];
    while(left < right) { 
        while(left < right && array[right] >= tmp) {
        right--;
    }
         array[left] = array[right];
        while(left < right && array[left] <= tmp) {
            left++;
        }
        array[right] = array[left];
        }
        array[left] = tmp;
        return left;
    }

}

七大排序算法复杂度及稳定性分析

排序算法二 归并排序和快速排序,Java数据结构,排序算法,算法,数据结构,java,开发语言文章来源地址https://www.toymoban.com/news/detail-731273.html

到了这里,关于排序算法二 归并排序和快速排序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【数据结构】快速排序,归并排序

    【数据结构】快速排序,归并排序

    1.hoare版本 根据动图的演示,整理的思路如下, 1.定义left,right,key。key默认是左边第一个元素,像两个指针,左边找比key大的,右边找比k小的,找到的话,交换二者,往返这个过程,当left与right相遇时,交换key和此时相遇的值. 单趟下来,6出现在正确的位置。 1.为什么大循环

    2024年01月20日
    浏览(11)
  • 【数据结构】非递归实现快速排序与归并排序

    【数据结构】非递归实现快速排序与归并排序

    递归是可以向非递归进行变化的: 比如很经典的 斐波那契数列 可以用 递归 实现也可以用 循环 实现 但是有些复杂的递归仅仅依靠循环是很难控制的, 所以我们需要借助数据结构中的 栈与队列 帮助我们用非递归模拟递归, 故有的时候我们说非递归不是递归却胜似递归 通过

    2024年01月21日
    浏览(17)
  • 【数据结构】 七大排序详解(贰)——冒泡排序、快速排序、归并排序

    【数据结构】 七大排序详解(贰)——冒泡排序、快速排序、归并排序

    ==冒泡排序(Bubble Sort)==也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会

    2024年02月09日
    浏览(48)
  • 【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现

    【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现

    归并排序是一种经典的排序算法,它使用了分治法的思想。下面是归并排序的算法思想: 递归地将数组划分成较小的子数组,直到每个子数组的长度为1或者0。 将相邻的子数组合并,形成更大的已排序的数组,直到最终得到一个完全排序的数组。 归并排序的过程可以分为三

    2024年01月22日
    浏览(15)
  • 【数据结构】冒泡,快速,直接插入,归并,选择排序

    【数据结构】冒泡,快速,直接插入,归并,选择排序

    🎊专栏【数据结构】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【Dream It Possible】 大一同学小吉,欢迎并且感谢大家指出我的问题🥰 目录   🎁冒泡排序 🏳️‍🌈图解 🏳️‍🌈实现过程 🏳️‍🌈代码 🎁快速排序 🏳️‍🌈图解 🏳️‍🌈实现过

    2024年02月06日
    浏览(115)
  • 数据结构——排序算法——归并排序

    数据结构——排序算法——归并排序

    在第二个列表向第一个列表逐个插入的过程中,由于第二个列表已经有序,所以后续插入的元素一定不会在前面插入的元素之前。在逐个插入的过程中,每次插入时,只需要从上次插入的位置开始,继续向后寻找插入位置即可。这样一来,我们最多只需要将两个有序数组遍历

    2024年02月09日
    浏览(13)
  • 数据结构和算法笔记4:排序算法-归并排序

    数据结构和算法笔记4:排序算法-归并排序

    归并排序算法完全遵循分治模式。直观上其操作如下: 分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。 解决:使用归并排序递归地排序两个子序列。 合并:合并两个已排序的子序列以产生已排序的答案。 我们直接来看例子理解算法的过程,下面是要排序

    2024年01月21日
    浏览(15)
  • 数据结构与算法—归并排序&计数排序

    数据结构与算法—归并排序&计数排序

    目录 一、归并排序 1、主函数 2、递归实现 3、优化递归  4、非递归实现 5、特性总结: 二、计数排序 1、代码: 2、特性总结: 三、各种排序总结 时间空间复杂度汇总  基本思想: 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用 分治法 的一个非常典型的

    2024年02月04日
    浏览(11)
  • 数据结构与算法:归并排序

    数据结构与算法:归并排序

    在讲解归并排序前,我们先看到一个问题: 对于这样两个有序的数组,如何将它们合并为一个有序的数组? 在此我们处理这个问题的思路就是:开辟一个新的数组,然后分别安置一个指针在左右数组,利用指针遍历数组,每次对比将比较小的那个元素插入到数组的尾部。 像

    2024年01月21日
    浏览(13)
  • 数据结构算法--5 归并排序

    数据结构算法--5 归并排序

    我们先看一下归并排序是怎么归并的  两个有序列表,有low指针指向2,high指针指向6,mid指针指向9 再建一个新列表,12,所以1放到列表,右指针右移一位,再比较2和3,2放入列表,左指针右移一位,以此类推,肯定有一部分列表率先没有数,这时将另一列表直接append进入新

    2024年02月11日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包