【数据结构】常用排序算法(包括:选择排序,堆排序,冒泡排序,选择排序,快速排序,归并排序)

直接插入排序:

在序列中,假设升序排序

1)从0处开始。

1)若走到begin =3处,将begin处元素保存给tmp,比较tmp处的元素与begin--处元素大小关系,若begin处<begin-1处,将begin-1处元素移动到begin;若大于,则不变化。再用tmp去和begin--处的元素用同样的方法去作比较,直至begin此时减少到数组起始坐标0之前结束。

3)以此类推,依次走完序列。

时间复杂度:O()

代码如下:


//Sequence in ascending order 
void InsertSort(int* a,int size)
{
    assert(a);
    for (int begin = 0; begin < size ; begin++)
    {
        int tmp = a[begin];
        int end = begin-1;
        while (end >= 0 && tmp < a[end])
        {
            a[end+1] = a[end];
            a[end] = tmp;
            end--;
        }
    }
}

2.希尔排序

希尔排序实际上是直接插入排序的优化和变形。假设升序排序

1)我们先去取一个增量值gap,将序列分为几组。

2)然后我们分组去排序。当每个分组排序排好后,相当于整个序列的顺序就排列好了。

3)比较a[i],a[i+gap]大小关系,若a[i]>a[i+gap],则交换。否则不处理。往后走,继续该步骤……

代码如下:


//Sequence in ascending order 
void ShellSort(int* a, int size)
{
    assert(a);
    int gap = size;
    while (gap > 1)
    {
        gap = gap / 3 + 1;
        for (int i = 0; i < size - gap; i++)
        {
            int end = i;
            int tmp = a[end + gap];
            while (end >= 0 && a[end] > a[end + gap])
            {
                a[end+gap] = a[end];
                a[end] = tmp;
                end -= gap;
            }
        }
    }
    
}

3.选择排序

假设升序排序

1)第1次遍历整个数组,找出最小(大)的元素,将这个元素放于序列为0(size-1)处。此时,未排序的序列不包括0(size-1)处.第2次,同样的方法找到找到剩下的未排序的序列中的最小的元素,放于序列为1处。

2)重复,直至排到序列结尾处,这个序列就排序好了。

时间复杂度:O(N^2)。

代码如下:


//Sequence in ascending order 
void SelectSort(int* a, int size)
{
    assert(a);
    
    for (int i = 0; i < size; i++)
    {
        int minnum = i;
        for (int j = i+1; j < size;j++)
        {
            if (a[minnum] > a[j])
            {
                minnum = j;
            }        
        }
        if (i != minnum)
        {
            swap(a[i], a[minnum]);
        }
        
    }
}

4.堆排序

假设升序排序

我们先要思考升序序列,我们需要建一个最大堆还是最小堆?

如果最小堆,那么每个根节点的元素大于它的子女节点的元素。但是,此时却不能保证她的左右节点一定哪个大于哪一个,且不能保证不同一层的左右子树的节点元素大小。

所以,要设计升序排序,我们需要建一个最大堆。

1)建一个最大堆。

2)第1次,将根节点的元素与堆的最后一个节点元素交换,这样肯定保证最大元素在堆的最后一个节点处,然后此时的根节点并不一定满足大于左右子女节点,因此将其向下调整,至合适位置处。第2次,将根节点的元素与堆的倒数第2个节点元素交换,向下调整交换后的根节点至合适位置……

代码如下:


void _AdjustDown(int parent, int* a, int size)
{
    int child = 2 * parent + 1;
    while (child < size)
    {
        if (child + 1 < size && a[child + 1] > a[child])
        {
            child++;
        }
        if (a[child] >a[parent])
        {
            swap(a[child], a[parent]);
            parent = child;
            child = 2 * parent + 1;
        }
        else
        {
            break;
        }
    }
}

//Sequence in ascending order 
void HeapSort(int* a, int size)
{
    assert(a);
    for (int i = (size - 2) / 2; i >= 0;i--)
    {
        _AdjustDown(i, a, size);
    }

    for (int i = 0; i < size -1; i++)
    {
        swap(a[0], a[size - i -1]);
        _AdjustDown(0, a, size-i-1);
    }
}

5.冒泡排序

假设升序排序

冒泡,顾名思义,像泡一样慢慢地沉。

1)第一次,比较a[0],a[1]大小,若a[0]>a[1],则交换它们。再比较a[1],a[2],若a[1]>a[2],则交换……这样一直到比较a[size-1],a[size]结束,此时已经将一个最大的元素沉到序列的最尾端size-1处了。

2)第二次,重复上述操作,可将次最大的元素沉到size-2处。

3)重复,完成排序。

比较:

冒泡排序是两两比较,每次将最大的元素往后沉。而选择排序不同的是,每次遍历选择出最大元素放到最后。

代码如下:


//Sequence in ascending order 
void BubbleSort(int* a, int size)
{
    assert(a);
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size - i -1; j++)
        {
            if (a[j] > a[j + 1])
            {
                swap(a[j], a[j + 1]);
            }
        }
    }
}

6.快速排序

快速排序,顾名思义,排序算法很快,它是最快的排序。时间复杂度为:O(n*lgn).适合于比较乱的 序列。假设升序排序

对于序列:{ 5, 1,8,12, 19, 3, 7, 2, 4 ,11}

1)我们取序列的第一个数据当做比较的基准,并且设定序号为0的位置为低位置low,序号为size-1的位置为高位置high。

2)取出序列的基准元素key,此刻的5.

在high位置从右往左找直到找到比基准值5小的元素,即此刻的元素4处停止。

然后,在low位置从左往右找直到找到比基准值5大的元素,即此刻的元素8停止。

由于此时的基准元素key被取出,存放它的位置就空下来了。将找到的元素4赋值给此刻的这个位置.

3)此时元素4存放的位置空下来了,将找到的低位置的8放到这个位置去。

4)重复这样的动作,2放到基准位置,12放到原来2的位置……

5)直到low>=high时停止。

以上是一次快速排序,在经过一次快速排序后,high与low相遇左右各形成有序序列。再将这个相遇位置左右各当成一个序列,继续进行快速排序,最终可以将序列排序好。

代码如下:

void QuickSort(int* a, int left,int right)
 {
    assert(a);
    int low = left;
    int high = right;
    int key = a[low];

    while (low < high)
    {                
        while (low < high && key <= a[high])
        {
            high--;
        }
        a[low] = a[high];

        while (low <high && key >= a[low])
        {
            low++;
        }
        a[high] = a[low];
    }
    a[low] = key;

    if (left <= high)
    {
        QuickSort(a, left, low - 1);
        QuickSort(a, low + 1, right);
    }
}
时间: 2024-08-25 01:55:17

【数据结构】常用排序算法(包括:选择排序,堆排序,冒泡排序,选择排序,快速排序,归并排序)的相关文章

排序算法(三)冒泡、选择排序的Python实现及算法优化详解

说在前面 最近一年太忙,博客长草了.近日用Python实现了常用排序算法,供大家参考. Java版本排序算法及优化,请看以前的文章. <排序算法之简单排序(冒泡.选择.插入)> <排序算法(二)堆排序> 1.排序概念 这里不再赘述,请参看前面2篇文章 2.简单排序之冒泡法Python实现及优化 原理图 2.1.基本实现 num_list = [     [1, 9, 8, 5, 6, 7, 4, 3, 2],     [1, 2, 3, 4, 5, 6, 7, 8, 9] ] nu

#排序算法#【3】堆排序

堆是一个完全二叉树,树中每个结点对应于原始数据的一个记录,并且每个结点应满足以下条件:非叶结点的数据大于或等于其左.右孩子结点的数据(若是按从大到小的顺序排序,则要求非叶结点的数据小于或等于其左.右孩子结点的数据). 由堆的定义可看出,其根结点为最大值,堆排序就是利用这一特点进行的.堆排序过程包括两个阶段: (1)将无序的数据构成堆(即用无序数据生成满足堆定义的完全二叉树). (2)利用堆排序(即用上一步生成的堆输出有序的数据). 加入有一组要排序的数据:69,65,90,37,92,6,28,

算法有插入排序,堆排序,合并排序,快速排序和stooge排序

比较的算法有插入排序,堆排序,合并排序,快速排序和stooge排序, 先说一下比较结果 1,比较插入和stooge排序,stooge的表现如此之差,数组大小在2000时 InsertSort VS StoogeSort 's Running Time:     16ms:47672ms; Terribly! Isn't It? 所以在后面的比较中,没有带stooge这个垃圾算法 2,插入排序,堆排序,合并排序,快速排序运行时间对比 (网易博客的表格功能太差了,不爽,只好以文本对齐展现给大家了):

常见排序算法详解(冒泡、选择、插入、快速、希尔、归并)

一.排序算法 1.冒泡排序(Bubble Sort) 定义:是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端. 原理: 比较相邻的元素.如果第一个比第二个大(升序),就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.这步做完后,最后的元素会是最大的数. 针对所有的元素重复以上的

常见的五类排序算法图解和实现(多关键字排序:基数排序以及各个排序算法的总结)

基数排序思想 完全不同于以前的排序算法,可以说,基数排序也叫做多关键字排序,基数排序是一种借助“多关键字排序”的思想来实现“单关键字排序”的内部排序算法. 两种方式: 1.最高位优先,先按照最高位排成若干子序列,再对子序列按照次高位排序 2.最低位优先:不必分子序列,每次排序全体元素都参与,不比较,而是通过分配+收集的方式. 多关键字排序 例:将下表所示的学生成绩单按数学成绩的等级由高到低排序,数学成绩相同的学生再按英语成绩的高低等级排序.        第一个关键字是数学成绩,第二个关键字是英

排序算法四:交换排序之冒泡排序

排序算法四:交换排序之冒泡排序 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 引言 在我的博文<"主宰世界"的10种算法短评>中给出的首个算法就是高效的排序算法.本文将对排序算法做一个全面的梳理,从最简单的"冒泡"到高效的堆排序等. 系列博文的前三篇讲述了插入排序的三种不同类型,本文讲述第二大类的排序算法:交换排序,包括冒泡排序和快速排序. 排序相关的的基本概念 排序:将一组杂乱无章的数据按一定的规律顺次排列起

三种线性排序算法(计数、基数、桶排序)的简单实现

一.计数排序 计数排序假设n个输入元素中的每一个都是介于0到k之间的整数.此处k为某个整数(输入数据在一个小范围内). 基本思想: 计数排序的基本思想是对每一个输入元素x,确定出小于x的元素的个数.然后再将x直接放置在它在最终输出数组中的位置上. 如下图所示: 由于数组中可能有相等的数,在处理时需要注意. 时间复杂度和空间复杂度分析 算法总时间Θ(k + n).当k=O(n)时,计数排序的运行时间是Θ(n). 空间复杂度是O(n+k).需要两个辅助数组:存放排序结果的数组B[n],存放临时结果的

排序算法(三)堆排序及有界堆排序Java实现及分析

1.堆排序基数排序适用于大小有界的东西,除了他之外,还有一种你可能遇到的其它专用排序算法:有界堆排序.如果你在处理非常大的数据集,你想要得到前 10 个或者前k个元素,其中k远小于n,它是很有用的. 例如,假设你正在监视一 个Web 服务,它每天处理十亿次事务.在每一天结束时,你要汇报最大的k个事务(或最慢的,或者其它最 xx 的).一个选项是存储所有事务,在一天结束时对它们进行排序,然后选择最大的k个.需要的时间与nlogn成正比,这非常慢,因为我们可能无法将十亿次交易记录在单个程序的内存中.

js排序算法总结——冒泡,快速,选择,插入,希尔,归并

相信排序是任何一个程序猿都会用到的东西,今天简单总结记录下常见的排序算法. 一.冒泡排序 说起冒泡排序,可能每个人都不会陌生,实现思路相当简单明了,就是不停的对数组进行两两比较,将较大(较小)的一项放在前面: 如 var arr = [7, 3, 10, 1, 8, 4, 2, 4, 4, 3] 进行升序排列,排序过程如下 第一次 [3, 7, 1, 8, 4, 2, 4, 4, 3, 10] 第二次 [3, 1, 7, 4, 2, 4, 4, 3, 8, 10] 以此类推 .... 结果 [1

排序算法合集(冒泡,选择,插入,堆排,快排)

1.冒泡排序 最初在学c语言时,老师就教的这个排序算法,原理比较简单:从数组下标为0处开始遍历,相邻之间进行比较,若a[i]>a[i+1],则exchange(a[i],a[i+1]),当然也可以将小的往后传递,将此过程不断进行,那么最后数组就有序了. 要点:(1)每遍历一遍,末尾就得到一个最大值(或最小值),那么接下来的遍历是不是每次都减少一个元素就好了,因为后边的已经排好序了啊. (2)遍历n-1遍就排好序了,因为最后一遍只剩一个元素了,它一定放那儿,所以最后一遍就不用遍历了. 当然如果数据