`
hojor
  • 浏览: 108738 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

基本排序算法总结

阅读更多

排序算法的评价

评价排序算法的一般准则是:
▶ 平均情况下的排序速度
▶ 最优最劣情况下的速度
▶ 行为是否自然
▶ 是否以相等的关键字重排元素

数组的排序速度直接与比较(comparison)次数和交换(exchange)次数相关,其中交换的作用更大,因为占用的时间多。
如果频繁遭遇到最优最劣情况,则最优和最劣情况下的运行时间是重要的。
所谓自然(natural)行为的排序应该是,对已排序的表操作最容易,对失序越重的表操作越困难。
通常,如果有相等关键字的元素在排序前后,之间的相对位置并不改变,我们称之为该排序是稳定的。




气泡排序(bubble sort)
      
最著名(也最声名狼藉)的排序是气泡排序。

void bubble_sort(char *items, int count)
{
    int i, j;
    char t;
   
    for(i = 1; i < count; i++)
    {
        for(j = count-1; j >= i; j--)
        {
            if(items[j-1] > items[j])
            {
                t = items[j-1];
                items[j-1] = items[j];
                items[j] = t;
            }
        }
    }
}

分析:
两个 for 循环重复了比较的次数,所以比较的次数是恒定的:1 / 2(n平方 - n)
其中,外部循环执行 n - 1 次,内部循环执行 n/2 次,两式相乘得到以上公式。
下面是气泡排序的动画演示:

气泡排序动画演示


选择排序(selection sort)

选择排序中,先选择最小的元素并将其与第一个元素进行交换。然后剩余的 n - 1 个元素中选择最小值者并与第二个元素交换等,如此直到最后两个元素。

void select_sort(char *items, int count)
{
    int i, j, k;
    int exchange;
    char t;

    for(i = 0; i < count -1; i++)
    {
        exchange = 0;
        t = items[i];
        k = i;

        for(j = i+1; j < count; j++)
        {
            if(items[j] < t)
            {
                t = items[j];
                k = j;
                exchange = 1;
            }
        }

        if(exchange)
        {
            items[k] = items[i];
            items[i] = t;
        }
    }
}


分析:
和气泡算法一样,选择排序需要进行的比较次数同样为 1/2 (n平方 - n) 。尽管如此,但在平均情况下,选择排序的交换次数要少得多。
下面是选择排序的动画演示:

选择排序动画演示


插入排序(Insertion sort)

插入排序中,先对前两个元素进行排序,然后把第三个元素按序插入到已排好序的前两个元素中。随后是第四个插入到已排好序的前三个元素中,以此类推,直到所有元素都有序为止。

void insert_sort(char *items, int count)
{
    int i, j;
    char t;
   
    for(i = 1; i < count; i++)
    {
        t = items[i];
        j = i - 1;

        while(j >= 0 && items[j] > t)
        {
            items[j+1] = items[j];
            j--;
        }

        items[j+1] = t;
    }
}


分析:
与气泡排序和选择排序不同的是,插入排序的比较次数与被排表的初始排列有关。如果表是完全有序的,比较 n - 1 次,否则按 n 平方次进行。

因此,最劣情况下,与 气泡排序和选择排序一样差,平均情况稍好一点。然而这种办法的确有两个优点:
1. 排序是自然的,即表已排序时工作量最少,反序时工作量最大。这样,对基本已排序的表操作时,插入排序是最理想的。
2. 排序是稳定的,即相同关键字元素的相对位置,排序前后保持不变。

下面是插入排序的动画演示:

插入排序动画演示


前面几个算法,执行时间都是 n 平方级的,对于大量数据而言,排序速度非常慢,有时会完全不实用。
下面是两个较快的算法



希尔排序(Shell sort)


希尔排序是根据其发明者的名字(D.L.Shell)命名的。其一般方法是从插入排序导出并基于增量减少 (diminishing increments)。例如,首先,对间隔三个位置的元素排序;然后,再对间隔两个位置的元素排序;最后,对相邻元素进行排序。

排序的每一遍涉及相对较少的元素或已恰当排序的元素。因此,希尔排序是高效的,每一遍都提高了有序性。
增量的准确序列可以变化,唯一规则是最后增量必须为 1 。例如:9 ,5, 3, 2, 1 。以 2 的幂为增量值的序列是不可取的,出于复杂的数学原理,这种序列降低了排序算法的效率。

void shell_sort(char *items, int count)
{
    int i, j, k, gap;
    int gaps[5];
    char t;

    gaps[0] = 9; gaps[1] = 5; gaps[2] = 3; gaps[3] = 2; gaps[4] = 1;

    for(k = 0; k < 5; k++)
    {
        gap = gaps[k];
       
        for(i = gap; i < count; i++)
        {
            t = items[i];
            j = i - gap;

            while(j >= 0 && items[j] > t)
            {
                items[j+gap] = items[j];
                j = j - gap;
            }

            items[j+gap] = t;
        }
    }
}

分析:
希尔排序的执行与 n 的1.2 次方 成比例,相对于 n 平方排序而言,这是重大改进。
下面是希尔排序动画演示:

希尔排序动画演示


快速排序(quick sort)

快速排序是又 C.A.R.Hoare 发明的,一般被认为是目前最好的通用排序算法。快速排序基于交换排序,与同样基于交换排序的 气泡排序相比,其效果是惊人的。

快速排序的基本思想是分区(partition)。一般过程是先选一个比较数(comparand)的值,然后把数组分成两段。大于等于分区值的元素都放在一边,小于分区值的元素放在另一边。然后对数组的另一段重复上述过程,直到该数组完成排序。

排序的过程本质上递归的,而实际上,快速排序的最清晰实现就是递归算法。

选择比较数值的办法有两个,可以随机选取也可以选取数组中一组值求平均值得到。


void quick_sort(char *items, int count)
{
    qs(items, 0, count - 1);
}

void qs(char *items, int left, int right)
{
    int i, j;
    char x, t;

    i = left; j = right;
    x = items[(left+right)/2];

    do
    {
        while(items[i] < x && i < right)
            i++;
        while(x < items[j] && j > left)
            j--;

        if(i <= j)
        {
            t = items[i];
            items[i] = items[j];
            items[j] = t;
            i++; j--;
        }
    }while(i <= j);

    if(left < j)
        qs(items, left, j);
    if(i < right)
        qs(items, i, right);
}


分析:
快速排序的平均比较次数为 n log n ,近似交换次数 n/6 log n 。这两个数值远小于前面各种排序的相应参数。
需要注意的一个问题是,如果每个分区的比较数值选择了最大值,快速排序退化成 n 平方操作时间的排序。
快速排序是分而治之(divide and conqer)的策略,请参考另外一种采用 分治 策略的排序方法:归并排序(Merge Sort)(zz)
与归并排序不同的是, 最劣情况下,快速排序的的时间复杂度为 n 平方,而归并排序则是 nlogn 。

这里的这个算法写的不够清晰,请参看 寻找第k小的数 与 快速排序

分享到:
评论

相关推荐

    十大经典排序算法总结.docx

    《十大经典排序算法总结》 排序算法是计算机科学的基础,其设计思想和效率对软件的性能有着直接影响。本文主要探讨了十种经典的排序算法,包括它们的设计思路、优缺点以及适用场景,帮助我们理解排序算法的核心。 ...

    C#排序算法总结

    C#排序算法总结涵盖了交换排序和插入排序两大类排序算法,其中交换排序包括了冒泡排序、选择排序和快速排序,而插入排序则涉及直接插入排序和折半插入排序。下面将详细介绍每种排序算法的实现原理、特点以及在C#中的...

    八大排序算法总结

    【排序算法总结】 排序是计算机科学中的一项基本操作,它涉及到如何有效地重新排列一组数据,使其按照特定的顺序排列。本文将重点介绍八大排序算法,包括插入排序、希尔排序、交换排序、快速排序、选择排序、堆排序...

    常用的排序算法总结(各种内部排序算法和外部排序算法)

    本文将对几种常见的内部排序算法和外部排序算法进行详细总结。 首先,排序的基本定义是:给定一个包含n个记录的序列,其关键字序列分别为K1, K2, ..., Kn,如果存在一个排列p1, p2, p3, ..., pn,使得关键字满足非...

    各种排序算法总结(ppt)

    在这个名为“各种排序算法总结(ppt)”的资料中,我们将会深入探讨多种常见的排序算法,包括它们的基本原理、优缺点以及实际应用。** 首先,我们要了解排序的目的是为了使数据有序,这在数据处理和分析中具有广泛...

    常见排序算法总结.pdf

    【排序算法总结】 排序算法是计算机科学中处理数据排列的重要工具,主要分为稳定排序和非稳定排序、内排序和外排序两大类。稳定排序保证了相同元素在排序后的相对位置不变,而非稳定排序则不作此保证。内排序是指...

    8种基本排序算法2015上

    根据提供的信息,我们可以总结出以下关于八种基本排序算法中的两种——冒泡排序(Bubble Sort)与插入排序(Insert Sort)的知识点。 ### 冒泡排序(Bubble Sort) #### 定义 冒泡排序是一种简单的排序算法。它...

    常用排序算法总结

    ### 常用排序算法总结 #### 一、冒泡排序 冒泡排序是一种简单的排序算法,它重复地遍历待排序的数列,依次比较相邻的两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复进行的,直到没有再需要...

    排序算法总结文档

    排序算法是计算机科学中最基础且重要的算法之一,用于将一组数据按照特定顺序排列。这里我们主要探讨五种经典的排序算法:选择排序、冒泡排序、插入排序、快速排序以及归并排序。 1. **选择排序**: 选择排序的...

    最经典的8大排序算法总结

    在本篇总结中,将探讨8种经典的排序算法,分别是冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序、二叉树排序和基数排序。 1. 冒泡排序(Bubble Sort): 冒泡排序是一种简单的排序算法。它重复地遍历要...

    八大经典排序算法总结和源代码

    八大经典排序算法总结和源代码 在计算机科学中,排序算法是最基本也是最重要的算法之一。排序算法的性能直接影响到整个系统的性能。今天,我们将总结八大经典排序算法,并提供C++实现的源代码。 一、稳定排序和...

    排序算法总结——最全、最新的排序算法

    排序算法总结——最全、最新的排序算法 本文对各种排序算法进行了总结,包括插入排序、选择排序、冒泡排序、快速排序和堆排序等。下面是对每种排序算法的详细介绍: 一、插入排序(Insertion Sort) 插入排序是一...

    排序算法总结.docx

    本文将对数据结构常见的八大排序算法进行详细阐述,包括它们的基本思想、工作原理以及适用场景。 1. 直接插入排序: 直接插入排序是一种简单直观的排序算法,它的工作原理类似于我们平时手动排序扑克牌。首先,假设...

    排序查找算法总结

    排序算法是计算机科学中的一种基本算法,用于对数据进行排序。在各种排序算法中,每种算法都有其特点和应用场景。本文将对10种经典的排序算法进行总结,并对每种算法的时间复杂度、空间复杂度和适用场景进行分析。 ...

    几种内部排序算法总结

    ### 几种内部排序算法总结 #### 冒泡排序(Bubble Sort) 冒泡排序是一种简单的排序算法,它重复地遍历待排序的数列,依次比较相邻的两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的,...

    常用排序算法总结(含Java代码)

    冒泡排序和快速排序是两种基础但广泛使用的数据排序算法。冒泡排序由于其简单直观的特性,易于理解和实现,而快速排序则以其较高的效率在数据量较大时展现出优势。 首先,让我们来看冒泡排序算法。冒泡排序通过重复...

    C++数据结构排序算法

    C++数据结构排序算法总结 在计算机科学中,排序算法是最基本和最重要的算法之一。在实际应用中,排序算法广泛应用于各种领域,如数据分析、机器学习、数据库管理等。C++数据结构排序算法总结将为您提供详细的排序...

Global site tag (gtag.js) - Google Analytics