快速排序和归并排序总结

  都是两种效率高而且常用的排序方法,今天来总结下。

  先说快排:

  首先,快速排序的时间复杂度为nlogn,其思想实质为分治法。而这分治法的基本思想为以下三点:

  1.先从数列中取出一个基准数。

  2.在分治的过程中,比这个基准数小的数全部放到这个基准数的左边,反之则放到右边。

  3.然后再对由第二步产生的两个区间再进行第二步的操作,当分出来的区间仅剩一个数为止。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define maxn 1000000
int a[maxn];

void qs(int a[],int l,int r)
{
    if(l < r)
    {
        int i=l, j=r, x=a[l];
        while(i < j)
        {
            while(i<j && a[j] >= x)
                j--;
            if(i < j)
                a[i++] = a[j];
            while(i<j && a[i] < x)
                i++;
            if(i < j)
                a[j--] = a[i];
        }
        a[i] = x;
        qs(a,l,i-1);
        qs(a,i+1,r);
     }
}

void print(int a[],int n)
{
    for(int i=0; i<n; i++)
        printf("%d ",a[i]);
    printf("\n");
}

int main()
{
    int n,i;
    while(scanf("%d",&n) == 1)
    {
        srand(time(0));
        for(i=0; i<n; i++)
            a[i] = rand()%100;
        qs(a,0,n-1);
        print(a,n);
    }

    return 0;
}

  这里我实现的版本是以第一个数为基准数,但是如果要按照升序排序的话而待排列数组又是降序的话,时间复杂度就成了n了。所以,有的方法是以待排列数组的中位数作为基准数的,要实现这个非常简单,将第一个元素与中位数交换即可。

  接下来再说归并排序:

归并排序是建立在归并操作上的一种非常有效的排序方法。同样,归并排序的实质也是分治思想。

  基本思想是将数组不断地分成两组,直至留下若干剩下一个或两个元素的小组。再合并这些小组。从而使得数组整体有序。

  应该来说在数据范围不是相当大的时候,归并排序和快速排序的耗时应该是差不多的,但是归并排序有一个额外的空间开销--他需要一个辅助数组来存放合并下来的两个组的元素(有序的)。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define maxn 1000000
int a[maxn],temp[maxn];

void ma(int a[],int l,int mid,int r,int temp[])
{
    int i = l, j = mid+1;
    int m = mid,n = r;
    int t = 0;
    while(i<=m && j<=n)
    {
        if(a[i] <= a[j]) temp[t++] = a[i++];
        else temp[t++] = a[j++];
    }

    while(i<=m) temp[t++] = a[i++];
    while(j<=n) temp[t++] = a[j++];

    for(i=0; i<t; i++)
        a[i+l] = temp[i];
}

void ms(int a[],int l,int r,int temp[])
{
    if(l < r)
    {
        int m = (l + r) >> 1;
        ms(a,l,m,temp);
        ms(a,m+1,r,temp);
        ma(a,l,m,r,temp);
    }
}

void print(int a[],int n)
{
    for(int i=0; i<n; i++)
        printf("%d ",a[i]);
    printf("\n");
}

int main()
{
    int n,i;
    while(scanf("%d",&n) == 1)
    {
        srand(time(0));
        for(i=0; i<n; i++)
            a[i] = rand()%100;
        ms(a,0,n-1,temp);
        print(a,n);
    }
    return 0;
}

  归并排序还有一个有趣的用途--可以用来求一个数组的逆序数。

  方法很简单,就是在合并的时候,加一行代码,示例如下:

  

void ma(int a[],int l,int mid,int r,int temp[])
{
    int i = l, j = mid+1;
    int m = mid,n = r;
    int t = 0;
    while(i<=m && j<=n)
    {
        if(a[i] <= a[j]) temp[t++] = a[i++];
        else
        {
            cnt  += (m-i+1); //如果a[i] 这是比 a[j]大,那么从a[i]其后面一共有m-i+1个数比a[j]大
            temp[t++] = a[j++];
        }
    }

    while(i<=m) temp[t++] = a[i++];
    while(j<=n) temp[t++] = a[j++];

    for(i=0; i<t; i++)
        a[i+l] = temp[i];
}

  那么把全局变量cnt 在main函数里定为0即可。

  

复制去Google翻译翻译结果

快速排序和归并排序总结

时间: 2024-10-28 12:41:45

快速排序和归并排序总结的相关文章

插入排序、冒泡排序、选择排序、希尔排序、快速排序、归并排序、堆排序和LST基数排序——C++实现

首先是算法实现文件Sort.h,代码如下: /* * 实现了八个常用的排序算法:插入排序.冒泡排序.选择排序.希尔排序 * 以及快速排序.归并排序.堆排序和LST基数排序 * @author gkh178 */ #include <iostream> template<class T> void swap_value(T &a, T &b) { T temp = a; a = b; b = temp; } //插入排序:时间复杂度o(n^2) template<

快速排序、归并排序、堆排序三种算法性能比较

快速排序.归并排序.堆排序三种排序算法的性能谁最好呢?网上查了一下说快速排序最快.其次是归并排序,最差的是堆排序:而理论上三种排序算法的时间复杂度都是O(nlogn),只不过快速排序最差的会达到O(n^2),但是数据的随机性会消除这一影响,今天就来实际比较一下: 1 #include <iostream> 2 #include<time.h> 3 using namespace std; 4 #define MAX 100000000 5 int data1[MAX],data2[

[problem]快速排序和归并排序

最近有时间了解下快速排序和归并排序. 开始觉得很难,一直没有啃这块骨头,现在发现理解了并不难. 快排的思路就是指定一个值,然后将小于他的排到其左边,大于他的排到其右边. 1 #include <iostream> 2 #include <set> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 7 class Solution { 8 public: 9 void qso

快速排序,归并排序,堆排序python实现

快速排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n^2),平均情况下为O(n*logn),是不稳定的排序 归并排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n*logn),平均情况下为O(n*logn),是稳定的排序 堆排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n*logn),平均情况下为O(n*logn),是不稳定的排序 1.快速排序 快速排序的介绍以及C语言实现在这里:快速排序C语言实现 本文介绍的是快速排序python实现: de

单向链表排序:快速排序和归并排序

归并排序改变链接 快速排序改变链接 快速排序改变节点值 所有源码和测试函数 对单向链表的排序有2种形式,只改变节点的值 和 只改变链接 // 节点 struct ListNode { int val; ListNode* next; ListNode(int v, ListNode* n = NULL) { val = v; next = n; } }; 本文链接:单向链表排序:快速排序和归并排序 参考资料链接: 链表排序(冒泡.选择.插入.快排.归并.希尔.堆排序): 1. 归并排序(改变链接

C# 插入排序 冒泡排序 选择排序 快速排序 堆排序 归并排序 基数排序 希尔排序

下面列出了数据结构与算法的八种基本排序:插入排序 冒泡排序 选择排序 快速排序 堆排序 归并排序 基数排序 希尔排序,然后是测试的例子.代码位置:http://download.csdn.net/detail/luozuolincool/8040027 排序类: public class Sortings { //插入排序 public void insertSort(int[] array) { int temp = 0; int index = 0; for (int i = 0; i <

七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)

 写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.因此排序掌握各种排序算法非常重要.对下面介绍的各个排序,我们假定所有排序的关键字都是整数.对传入函数的参数默认是已经检查好了的.只是简单的描述各个算法并给出了具体实现代码,并未做其他深究探讨. 基础知识: 由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程.另一类是外部排序,

Java实现单链表的快速排序和归并排序

本文描述了LeetCode 148题 sort-list 的解法. 题目描述如下: Sort a linked list in O(n log n) time using constant space complexity. 题目要求我们在O(n log n)时间复杂度下完成对单链表的排序,我们知道平均时间复杂度为O(n log n)的排序方法有快速排序.归并排序和堆排序.而一般是用数组来实现二叉堆,当然可以用二叉树来实现,但是这么做太麻烦,还得花费额外的空间构建二叉树,于是不采用堆排序. 故本

九种经典排序算法详解(冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序,计数排序,桶排序,基数排序)

综述 最近复习了各种排序算法,记录了一下学习总结和心得,希望对大家能有所帮助.本文介绍了冒泡排序.插入排序.选择排序.快速排序.归并排序.堆排序.计数排序.桶排序.基数排序9种经典的排序算法.针对每种排序算法分析了算法的主要思路,每个算法都附上了伪代码和C++实现. 算法分类 原地排序(in-place):没有使用辅助数据结构来存储中间结果的排序**算法. 非原地排序(not-in-place / out-of-place):使用了辅助数据结构来存储中间结果的排序算法 稳定排序:数列值(key)