精华内容
下载资源
问答
  • 归并排序 数据结构

    2009-12-11 14:01:53
    (1)输入一组数,用递归和非递归程序实现归并排序 (2)分析归并排序的复杂度 (3)将归并排序的思想用于外部排序中
  • 归并排序 经典数据结构算法 ppt.
  • 主要介绍了java数据结构排序算法之归并排序,结合具体实例形式详细分析了归并排序的原理、实现技巧与相关注意事项,需要的朋友可以参考下
  • 归并排序算法 可以归并排序任意整数集合 显示清晰,界面友好
  • 数据结构》严蔚敏版——归并排序
  • 二路归并和多路归并排序PPT数据结构课件
  • C语言实现数据结构归并排序

    万次阅读 2018-09-19 09:48:21
    C/C++实现数据结构之2路-归并排序 归并排序和交换排序、选择排序的思想不一样,归并的含义是将两个或两个以上的有序表组合成一个新的有序表。假定待定排序表含有n个记录,则可以看成是N个有序的子表。每个子表长度为...

    C/C++实现数据结构之2路-归并排序

    归并排序和交换排序、选择排序的思想不一样,归并的含义是将两个或两个以上的有序表组合成一个新的有序表。假定待定排序表含有n个记录,则可以看成是N个有序的子表。每个子表长度为1,然后两两归并,得到N/2个长度为2或1的有序表。再两两归并。如此重复,直到获得一个长度为n的有序表为止。这种方法称为2路归并排序

    函数实现:

    merge()函数的功能是将两个有序表归并为一个有序表,其中我们需要使用到辅助数组arr2来存储排序结果。在这里我们假设对数组进行操作。不对有序表结构进行排序。由于数组的下标是从0开始,就变得和普通的有序表不同。一般来说。有序表的第0个元素在排序中会作为哨兵元素。哨兵元素的种种好处在这里就不在阐述了。

    设两段有序表A[low,mid],B[mid+1,high]存放在同一顺序表中相邻的位置上。每次从数组中找两个数,进行大小比较,然后存入辅助数组,然后重复执行这个操作。直到其中一段有序表被遍历完毕。即这里的循环条件可以设为
    low<mid&&mid+1<high(伪代码)

    当其中一段有序表被遍历完后,我们可以将另一段有序表直接存入辅助数组。由于是有序表,所以直接存入辅助表不会导致有序表的特性被破坏。

    下面我们来看代码
    int arr1[10] = {9,8,7,6,5,4,3,2,1,0}, arr2[10];//原数组arr1,临时空间数组arr2
    void merge(int low, int mid, int high) {
    	int i = low, j = mid + 1, k = low;
    	while (i <= mid && j <= high)
    		if (arr1[i]<arr1[j])
    			arr2[k++] = arr1[i++];
    		else
    			arr2[k++] = arr1[j++];
    	while (i <= mid)
    		arr2[k++] = arr1[i++];
    	while (j <= high)
    		arr2[k++] = arr1[j++];
    	for (i = low; i <= high; i++) {
    		arr1[i] = arr2[i];
    	}
    }
    

    上述代码中的while循环只会执行一个!!!!!

    以上代码只能将两个有序表合并为一个有序表。但是由于程序刚开始的时候,有序表为单个元素本身,所以我们需要一个递归来使我们的merge函数每次执行时的表都为有序表。这个我们需要通过一个函数mergesort来操控。

    void mergeSort(int a, int b) {
    	//直到a=b时,停止递归。
    	if (a<b) {
    		int mid = (a + b) / 2;
    		mergeSort(a, mid);
    		mergeSort(mid + 1, b);
    		merge(a, mid, b);
    	}
    }
    
    

    当a=b时,递归停止,那么a减b的绝对值仅为1,那么能够保证第一次传入Merge函数的是一个有序子表。从而导致每次传入的表都为有序子表。

    完整代码

    #include "stdio.h"
    
    int arr1[10] = {9,8,7,6,5,4,3,2,1,0}, arr2[10];//原数组arr1,临时空间数组arr2
    void merge(int low, int mid, int high) {
    	int i = low, j = mid + 1, k = low;
    	while (i <= mid && j <= high)
    		if (arr1[i]<arr1[j])
    			arr2[k++] = arr1[i++];
    		else
    			arr2[k++] = arr1[j++];
    	while (i <= mid)
    		arr2[k++] = arr1[i++];
    	while (j <= high)
    		arr2[k++] = arr1[j++];
    	for (i = low; i <= high; i++) {
    		arr1[i] = arr2[i];
    	}
    }
    
    void mergeSort(int a, int b) {
    	//直到a=b时,停止递归。
    	if (a<b) {
    		int mid = (a + b) / 2;
    		mergeSort(a, mid);
    		mergeSort(mid + 1, b);
    		merge(a, mid, b);
    	}
    }
    
    int main() {
    	int i;
        mergeSort(0, 9);
    	return 0;
    }
    
    

    当然你们也可以使用动态定义的方式来定义数组,那么这里传入mergeSort的参数就需要改变了。

    展开全文
  • 本篇文章讲解三个高级排序算法,分别为希尔排序、归并排序、快速排序。虽然它们的思想很复杂,但真的运用得非常得巧妙,我会用丰富的例子以及动图来让大家轻松地理解并掌握。

    本系列文章【数据结构与算法】所有完整代码已上传 github,想要完整代码的小伙伴可以直接去那获取,可以的话欢迎点个Star哦~下面放上跳转链接

    本篇文章来讲解一下更高级的排序算法,顾名思义,它们的排序思想一定更复杂,效率也一定比简单排序更高。为了更方便地理解高级排序算法,还是建议大家先把简单排序了解清楚,因为高级排序也多少借鉴了简单排序的思想,下面放上文章链接

    【数据结构与算法】简单排序(冒泡排序、选择排序、插入排序)完整思路,并用代码封装排序函数

    那么就让我们来了解一下三种高级排序算法吧

    一、希尔排序

    希尔排序是插入排序的改进版本,弥补了插入排序在某些情况下的缺点。

    例如,当长度为100的数组,前面有序区域的数组长度为80,此时我们用第81个数去跟前面有序区域的所有元素比较大小,但恰巧第81个数又是这100个数里最小的,它本应该在索引为1的位置,如图所示

    在这里插入图片描述
    本例中第81个数据的值为1,那么前面有序区域里的80个元素都要往后移动一个位置,这种情况就非常影响排序性能。

    因此,我们就要想办法尽可能早点让小的值靠前,让大的值靠后,这样就能避免上述情况了,这就是希尔排序要解决的问题。

    希尔排序也叫做缩小增量排序,它通过先设置一个增量n,大小为数组长度的一半,将间隔为n的元素视作一个组,然后对每个组内部的元素进行从小到大进行插入排序;然后再将增量n缩小一半,再次进行分组插入排序,直到增量n为1,因为增量为1的时候,所有的元素都为同一个组了


    为了方便大家理解,我用一个例子来展示一个完整的希尔排序过程,首先数据的初始状态如图所示,这里为了更好地体现希尔排序的优点,我特地把值较大的元素放到了靠左的位置,把值较小的元素放到了靠右的位置

    在这里插入图片描述
    该数组长度为8,因此我们设置初始的增量为 8 / 2 = 4,那么该数组的分组情况如下图所示:

    在这里插入图片描述
    图中颜色相同的元素为一组,每组内的各个元素间隔都为4,现在对每个组内进行从小到大排序,排序结果如下图所示:

    在这里插入图片描述
    此时我们将增量缩小一半,即 4 / 2 = 2,同样的,现在将所有元素重新组合,把所有间隔为2的元素视作一组,分组结果如下图所示:

    在这里插入图片描述

    图中颜色相同的元素为一组,每组内的各个元素间隔都为2,现在对每个组内进行从小到大排序,排序结果如下图所示:

    在这里插入图片描述
    我们继续将增量缩小一半,即 2 / 2 = 1,同样的,现在将所有元素重新组合,把所有间隔为1的元素视作一组,此时所有的元素都为同一组了,就相当于对所有的数据进行普通的插入排序,我们可以看到,对比最开始的数据,总得来说,小的值都比较靠左了,大的值也都比较靠右了,这样排序起来效率就很高了。结果如下图所示:

    在这里插入图片描述

    接下来用一个动图,演示一下完整的希尔排序全过程

    在这里插入图片描述
    了解完了希尔排序的实现过程,我们现在用代码来封装一下

    function shellSort(arr) {
        // 1. 获取数组长度
        let length = arr.length
    
        // 2.获取初始的间隔长度
        let interval = Math.floor(length / 2)
    
        // 3. 不断地缩小间隔的大小,进行分组插入排序
        while(interval >= 1) {
    
            // 4. 从 arr[interval] 开始往后遍历,将遍历到的数据与其小组进行插入排序
            for(let i = interval; i < length; i++) {
                let temp = arr[i]
                let j = i
                while(arr[j - interval] > temp && j - interval >= 0) {
                    arr[j] = arr[j - interval]
                    j -= interval 
                }
    
                arr[j] = temp           
            }
    
            // 5. 缩小间隔
            interval = Math.floor(interval / 2)
        }
    
        return arr
    }
    

    来用刚才举得例子来验证一下我们封装的希尔排序是否正确

    let arr = [63, 76, 13, 44, 91, 8, 82, 3]
    let res = shellSort(arr)
    console.log(res)
    /* 打印结果
    [3, 8, 13, 44, 63, 76, 82, 91]
    */
    

    上述情况中,希尔排序最坏情况下的时间复杂度为O(n²)。其实希尔排序的时间复杂度跟增量也有关系,我们上面是通过数组长度一直取一半获取的增量,其实还有一些别的增量规则,可以使得希尔排序的效率更高,例如Hibbard增量序列Sedgewick增量序列,本文就不对这两种增量做过多的讲解了,大家可以去网上搜索一下。

    二、归并排序

    归并排序的实现是使用了一种分而治之的思想,即将一个数组不断地通过两两分组的方式进行比较大小,最后直到所有元素都被分到一组里,那自然就是整体有序的了。

    我们来看一下归并排序的主要思路,首先有如下图所示排列的一组数据:

    在这里插入图片描述
    首先从左往右,每两个元素视为一组,组合前要分别判断一下这两个元素的大小,小的在左,大的右,如图所示

    在这里插入图片描述
    继续再取两个元素组成一组并比较大小,如图所示:

    在这里插入图片描述
    继续上一个步骤,如图所示:

    在这里插入图片描述
    此时,原数组的所有元素都被两两分组完毕了,现在整个数组的长度变成了3,如下图所示:

    在这里插入图片描述
    此时,我们要重新从左向右,每次取两个元素组成一组,同时分别比较两个元素内的所有子元素的大小,因为此时的两个元素内部是有序的,所以我们比较两者大小的话,只需要每次比较数组的第一个元素即可,过程如下图所示:

    在这里插入图片描述
    此时原数组中只剩下一个元素了,所以就不对其做任何组合处理了,此时的数组是这样的:

    在这里插入图片描述
    此时的数组内只有两个元素了,所以我们只需要不断比较两个元素内部的子元素大小,即可获得完整的有序数组了,过程如下图所示:

    在这里插入图片描述
    这就是一个完整的归并排序的过程,接下来我们用代码来实现一下吧

    function mergeSort(arr) {
        
        // 将所有元素不断地两两组合,直到所有元素都被组合成一个组
        while(arr.length > 1){
            // 获取一下遍历前的数组长度,方便下面判断需要组合几次
            let length = arr.length
            
            // 创建空的新数组,用于存放所有组合后的元素
            let next_arr = []
            
            // 取两个元素进行组合,一共取 length / 2 次
            for(let i = 0; i < Math.floor(length / 2); i++){
                // 取出第一个元素
                let left = [].concat(arr.shift())
                // 取出第二个元素
                let right = [].concat(arr.shift())
                // 创建另一个新的空数组,用于存放组合后的所有元素
                let new_arr = []
    
                // 取两个数组中头部最小的值放到新数组中,直到一个数组为空
                while(left.length > 0 && right.length > 0){
                    let min = left[0] > right[0]? right.shift() : left.shift()
                    new_arr.push(min)
                }
                // 将合并好的数组添加到新的数组中
                next_arr.push(new_arr.concat(left.length == 0? right : left))
            }
            // 判断是否有一个未成组的数组
            if(arr.length == 1) next_arr.push(arr[0]);
            
            // 将所有组合后的元素构成的新数组作为下一次遍历的对象
            arr = next_arr
        }
    
        // 返回完整有序数组
        return arr[0]
    }
    

    我们来使用一下该方法,看看是否正确,为了方便大家理解,我在归并排序的函数里加了一条打印的代码,可以看到每次遍历后的数组情况,结果如下

    let arr = [19, 97, 9, 17, 1, 8]
    mergeSort(arr)
    
    /* 打印结果:
    第一次组合后:[ [ 19, 97 ], [ 9, 17 ], [ 1, 8 ] ]
    第二次组合后:[ [ 9, 17, 19, 97 ], [ 1, 8 ] ]
    第三次组合后:[ [ 1, 8, 9, 17, 19, 97 ] ]
    */
    

    查看代码我们不难发现,归并排序运行起来非常得占内存,因为在组合的过程中,我们不断得在创建新的数组,然后又进行合并。但其比较次数却非常得少,只在每次合并元素时进行比较,因此归并排序的效率还是非常得高的。

    三、快速排序

    快速排序相信大家一定不陌生,就算没用过也一定听过,拥有这么大的名声,那么它的排序效率一定很高。而且快速排序也是面试中经常会被问到的,可能会让你当场手写哦~所以大家一定要掌握它的核心思想

    快速排序也用到了分而治之的思想,它的实现思路非常得有意思:

    1. 先选一个元素作为基点pivot
    2. 将其余元素中所有比pivot小的值放到pivot的左边;将所有比pivot大的值放到pivot的右边
    3. 然后分别对pivot左边的所有元素、pivot右边的所有元素从步骤1开始排序依次,直到所有元素完整有序

    思路看着很简单,那么我们来用一个例子具体看一下快速排序的全过程吧

    首先有这样一组数据,如下图所示:

    在这里插入图片描述
    首先我们要选取一个元素作为基点pivot,最后排序完后,pivot左边的所有元素都是小于pivot的,右边的所有元素都是大于pivot的,因此我们希望的是尽量是两边平均一下,所以这里将采用一种方式寻找到一个大概的中点,即取数组两头的索引,分别为left 、right,再取一个中点 center,结果如下图:

    在这里插入图片描述

    然后在这三个元素中找到一个中等大小的值,并将其放到数组的开头位置,如下图所示:

    在这里插入图片描述

    到此,我们就可以将该数组的第一个元素作为此次遍历的基点pivot了,同时,我们将引入两个指针,即 ij,分别指向 left 和 right,如图所示

    在这里插入图片描述

    接下来就可以进行遍历了,这里我们把遍历过程称为填坑法,因为现在我们取到了数组的第一个值为pivot,所以可以假设这个位置上没有元素了,留了一个坑,需要我们将别的元素填进来。所以我们要从指针 j 开始往右寻找到一个比pivot小的值,若找到了,则将找到的值填到坑里,但要注意的是,指针 j 不能找到 指针 i 的左边去,即当指针 j 与 指针 i 重合时就停止移动。

    过程如下图所示:

    在这里插入图片描述

    此时我们可以看到,指针 j 找到了一个小于pivot的值 8,并将找到的值填到了坑里,那么此时指针 j 所指向的位置就留下了一个坑,又需要别的元素来填坑,所以此时我们就要让指针 i 向右找一个大于pivot的值,并将值填到坑里,同样的,指针 i 也不能找到指针 j 的右边,即当指针 i 与 指针 j 重合时就停止移动。

    过程如下图所示:

    在这里插入图片描述

    指针 i 找到了一个大于pivot的值 97 并将其填到了坑里,此时指针 i 所在的位置就留下了一个坑,因此我们又要让指针 j 往左找小于pivot的值并填到坑里,过程如图所示:

    在这里插入图片描述

    紧接着,指针 i 又要向右找大于pivot的值,但是移动了两个位置都没有找到,并且此时指针 i 指针 j 重合了,此时我们只需要将pivot填入到坑里就实现了pivot左边的所有元素小于它,右边所有的元素都大于它了,如图所示:

    在这里插入图片描述

    接下来的操作,就是我们要单独对此时pivot的左边所有元素和右边的所有元素进行上述的一系列操作,就可以实现快速排序了。本例中的左右两边区域的元素个数都是小于等于3个的,因此直接将这几个值互相进行比较大小比较方便,过程如下图:

    在这里插入图片描述

    了解了快速排序的实现思路,我们来用代码来实现一下

    function quickSort(arr) {
        // 两个数据进行交换
        function exchange(v1, v2) {
            let temp = arr[v1]
            arr[v1] = arr[v2]
            arr[v2] = temp
        }
        
        // 找到相对合适的元素放到数组索引为0的位置作为基点pivot
        function init(left, right) {
            let center = Math.floor((left + right) / 2)
    
            // 比较索引为left、center、right三个值的大小,从小到大排列
            if(arr[left] > arr[right]) exchange(left, right)
            if(arr[center] > arr[right]) exchange(center, right)
            if(arr[left] > arr[center]) exchange(left, center)
    
            // 判断数组长度是否大于3,若小于3,则数组已经排序好了,不需要做任何处理
            if(right - left > 2) exchange(left, center)
        }
    
        function quick(left, right) {
            init(left, right)
            // 若数组长度小于等于2,则不需要做任何操作了,因为init函数已经排序好了
            if(right - left <= 2) return;
            
            // 创建指针i和j,分别指向left和right
            let i = left
            let j = right
            // 将该数组区域的第一个元素作为基点pivot
            let pivot = arr[i]
    
            // 不断让指针i和j寻找合适的值填坑,直到两个指针重合
            while(i < j) {
                // 指针j不断向左找小于pivot的值,但指针j不能找到指针i的左边
                while(arr[j] > pivot && j > i) {
                    j --
                }
                // 将找到的小于pivot的值填到指针i所指向的坑中
                arr[i] = arr[j]
    
                // 指针i不断向右找大于pivot的值,但指针i不能找到指针j的右边
                while(arr[i] < pivot && i < j) {
                    i ++
                }
                // 将找到的大于pivot的值填到指针j所指向的坑中
                arr[j] = arr[i]
            }
    
            // 将pivot填到指针i和指针j共同指向的坑中
            arr[i] = pivot
    
            // 对此时pivot的左边所有元素进行快排
            quick(left, i - 1)
            // 对此时pivot的右边所有元素进行快排
            quick(i + 1, right)
        }
    
        quick(0, arr.length - 1)
    
        return arr  
    }
    

    我们可以简单来验证一下快速排序的正确性

    let arr = [19, 97, 9, 17, 8, 1]
    console.log(quickSort(arr))
    /* 打印结果为:
    	[1, 8, 9, 17, 19, 97]
    */
    

    四、结束语

    排序算法中的高级排序(希尔排序、归并排序、快速排序)就已经讲完啦,下一篇文章为动态规划

    大家可以关注我,之后我还会一直更新别的数据结构与算法的文章来供大家学习,并且我会把这些文章放到【数据结构与算法】这个专栏里,供大家学习使用。

    然后大家可以关注一下我的微信公众号:前端印象,等这个专栏的文章完结以后,我会把每种数据结构和算法的笔记放到公众号上,大家可以去那获取。

    或者也可以去我的github上获取完整代码,欢迎大家点个Star

    我是Lpyexplore,一个因Python爬虫而进入前端的探索者。创作不易,喜欢的加个关注,点个收藏,给个赞~

    展开全文
  • 主要介绍了数据结构归并排序的实例详解的相关资料,这里对归并排序进行详细介绍,需要的朋友可以参考下
  • 排序算法_插入排序,快排,归并排序数据结构和算法入门3】
  • 关于序列的归并排序,涉及到序列的长度
  • 数据结构--归并排序.cpp
  • 数据结构归并排序

    2013-05-07 23:01:27
    简单易懂的归并排序,C语言写的。包看包懂......
  • 数据结构-归并排序

    2012-12-30 19:48:20
    数据结构-归并排序 PPT文档
  • 归并排序,排序等算法,数据结构,快速排序,链表排序归并排序,排序等算法,数据结构,快速排序,链表排序
  • C语言数据结构 链表与归并排序实例详解 归并排序适合于对链表进行原址排序,即只改变指针的连接方式,不交换链表结点的内容。 归并排序的基本思想是分治法:先把一个链表分割成只有一个节点的链表,然后按照一定顺序...
  • 数据结构归并排序.pdf
  • 分类目录——数据结构笔记 先把整个序列对半拆分,然后对子序列在进行对半拆分,直直拆成每个子序列只有一个元素, 然后再按拆分顺序一层一层反向合并,在拆分过程中原来在一个子序列的,合并后还在子序列,合并时...
  • 数据结构归并排序

    千次阅读 2017-08-30 15:44:17
    归并排序 基本思想   归并排序是建立在二路归并和分治法的基础上的一个高效排序算法,将已有序的子序列合并,得到完全有序的序列;即先使每个子序 列

    归并排序







    基本思想

                                                                                  

    归并排序是建立在二路归并和分治法的基础上的一个高效排序算法, 将已有序的子序列合并,得到完全有序的序列;即

    先使每个子序 有序,再使子序列段间有序。若将两个有序表合并成一个有序表, 称为 二路归并


    将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这

    些有序序列 次归并,得到 n/4 个长度为 4 的有序序列;如此反复进行下去,最后得到一个长度为 n 的有序序列。所以呢

    ,我们总结一下归并排序 就只有两步:


    分解:将有序序列不断地分裂,直到每个区间都只有一个数据为止.

    合并:将两个区间合并为一个有序的区间,一直合并知道只有一个区间为止.



    图是我偷来的,但是学习是认真的.

    分解的过程我们很容易想明白的,用递归就可以.但是我们今天最主要的步骤是合并,你要将两个区间合并为一个有序

    的区间你会怎 么思 考呢?

    这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比

    较,如果有数 列为空,那直接将另一个数列的数据依次取出即可。

    代码实现:

    /将有序数组a[]和b[]合并到c[]中  
    void MemeryArray(int a[], int n, int b[], int m, int c[])  
    {  
        int i, j, k;  
      
        i = j = k = 0;  
        while (i < n && j < m)  
        {  
            if (a[i] < b[j])  
                c[k++] = a[i++];  
            else  
                c[k++] = b[j++];   
        }  
      
        while (i < n)  
            c[k++] = a[i++];  
      
        while (j < m)  
            c[k++] = b[j++];  
    }  


    其实我们发现这种做法效率其实还是蛮高的,效率达到了O(N).现在我们解决了合并的问题.

    现在总的来看一下归并排序的做法,通过先递归的分解数列(将数列分解成只有一个元素的区间),再合并数列就完成了归并排序。




    代码实现

                                                                  

    //将有二个有序数列a[first...mid]和a[mid...last]合并。  
    void mergearray(int a[], int first, int mid, int last, int temp[])  
    {  
        int i = first, j = mid + 1;  
        int m = mid,   n = last;  
        int k = 0;  
          
        while (i <= m && j <= n)  
        {  
            if (a[i] <= a[j])  
                temp[k++] = a[i++];  
            else  
                temp[k++] = a[j++];  
        }  
          
        while (i <= m)  
            temp[k++] = a[i++];  
          
        while (j <= n)  
            temp[k++] = a[j++];  
          
        for (i = 0; i < k; i++)  
            a[first + i] = temp[i];  
    }  
    void mergesort(int a[], int first, int last, int temp[])  
    {  
        if (first < last)  
        {  
            int mid = (first + last) / 2;  
            mergesort(a, first, mid, temp);    //左边有序  
            mergesort(a, mid + 1, last, temp); //右边有序  
            mergearray(a, first, mid, last, temp); //再将二个有序数列合并  
        }  
    }  
      
    bool MergeSort(int a[], int n)  
    {  
        int *p = new int[n];  
        if (p == NULL)  
            return false;  
        mergesort(a, 0, n - 1, p);  
        delete[] p;  
        return true;  
    }  



    总结

                                                                                

    归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程

    ,时间复杂度 可以记为O(N),故一共为O(N*logN)。因为归并排序每次都是在相邻的数据中进行操作,所以归并排序

    在O(N*logN)的几种排序方 法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。


    算法名称  最差时间复杂度  平均时间复杂度  最优时间复杂度  空间复杂度  稳定性

    归并排序    O(NlogN)    O(NlogN)              O(NlogN)       O(n)        稳定


    所有排序当中用的最多的就是堆排序,快速排序,归并排序.

    若从空间复杂度来考虑:首选堆排序,其次是快速排序,最后是归并排序。

    若从稳定性来考虑,应选取归并排序,因为堆排序和快速排序都是不稳定的。

    若从平均情况下的排序速度考虑,应该选择快速排序。 








    展开全文
  • 数据结构中的内部排序法 归并排序 非常的好用
  • 主要介绍了C语言中数据结构之链表归并排序实例代码的相关资料,需要的朋友可以参考下
  • 数据结构例程——归并排序

    千次阅读 2015-11-30 20:56:46
    本文是[数据结构基础系列(9):排序]中第8课时[归并排序]的例程。#include #include #define MaxSize 20 typedef int KeyType; //定义关键字类型 typedef char InfoType[10]; typedef struct //记录类型 { KeyType...

    本文是[数据结构基础系列(9):排序]中第8课时[归并排序]的例程。

    #include <stdio.h>
    #include <malloc.h>
    #define MaxSize 20
    typedef int KeyType;    //定义关键字类型
    typedef char InfoType[10];
    typedef struct          //记录类型
    {
        KeyType key;        //关键字项
        InfoType data;      //其他数据项,类型为InfoType
    } RecType;              //排序的记录类型定义
    
    void Merge(RecType R[],int low,int mid,int high)
    {
        RecType *R1;
        int i=low,j=mid+1,k=0; //k是R1的下标,i、j分别为第1、2段的下标
        R1=(RecType *)malloc((high-low+1)*sizeof(RecType));  //动态分配空间
        while (i<=mid && j<=high)       //在第1段和第2段均未扫描完时循环
            if (R[i].key<=R[j].key)     //将第1段中的记录放入R1中
            {
                R1[k]=R[i];
                i++;
                k++;
            }
            else                            //将第2段中的记录放入R1中
            {
                R1[k]=R[j];
                j++;
                k++;
            }
        while (i<=mid)                      //将第1段余下部分复制到R1
        {
            R1[k]=R[i];
            i++;
            k++;
        }
        while (j<=high)                 //将第2段余下部分复制到R1
        {
            R1[k]=R[j];
            j++;
            k++;
        }
        for (k=0,i=low; i<=high; k++,i++) //将R1复制回R中
            R[i]=R1[k];
    }
    
    void MergePass(RecType R[],int length,int n)    //对整个数序进行一趟归并
    {
        int i;
        for (i=0; i+2*length-1<n; i=i+2*length)     //归并length长的两相邻子表
            Merge(R,i,i+length-1,i+2*length-1);
        if (i+length-1<n)                       //余下两个子表,后者长度小于length
            Merge(R,i,i+length-1,n-1);          //归并这两个子表
    }
    void MergeSort(RecType R[],int n)           //自底向上的二路归并算法
    {
        int length;
        for (length=1; length<n; length=2*length) //进行log2n趟归并
            MergePass(R,length,n);
    }
    int main()
    {
        int i,n=10;
        RecType R[MaxSize];
        KeyType a[]= {9,8,7,6,5,4,3,2,1,0};
        for (i=0; i<n; i++)
            R[i].key=a[i];
        printf("排序前:");
        for (i=0; i<n; i++)
            printf("%d ",R[i].key);
        printf("\n");
        MergeSort(R,n);
        printf("排序后:");
        for (i=0; i<n; i++)
            printf("%d ",R[i].key);
        printf("\n");
        return 0;
    }
    展开全文
  • 文章详细总结了插入排序、希尔排序、选择排序、归并排序、交换排序(冒泡排序、快速排序)、基数排序、外部排序。从`思想`到`代码实现`。 大三党,大数据专业,正在为面试准备,欢迎学习交流`。
  • 数据结构归并排序

    千次阅读 2020-07-14 10:34:41
    归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段...
  • 归并排序(Merging Sort)是与插入排序、交换排序、选择排序不同的另一类排序方法。归并的含义时将两个(二路归并)或两个以上(多路归并)的有序表合并成一个新的有序表。此处只讨论二路归并。基本思想将待排序序列r...
  • (五) 数据结构 - 归并排序

    千次阅读 2019-12-08 20:17:20
    归并排序 归并排序是一种基于分而治之的排序技术。最坏情况下的时间复杂度为O(nlogn),它是最受人尊敬的算法之一。归并排序首先将数组分成相等的两半,然后以排序的方式将它们合并。 核心思想 为了理解合并...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 62,917
精华内容 25,166
关键字:

归并排序的数据结构

数据结构 订阅