数据结构06:排序

本文深入探讨了排序算法的基本概念,包括稳定性、插入类排序、交换类排序、选择类排序、归并类排序和基数类排序。详细阐述了直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、二路归并排序和基数排序的执行流程、算法实现及性能分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

排序的基本概念

  1. 稳定性:原数据中相等的两个元素次序在经过该排序算法之后次序不变,则称该算法是稳定的
  2. 排序算法的分类
    1、插入类排序:在一个有序的列表中插入一个新的记录
    例如:直接插入拍哦徐、这般插入排序、希尔排序
    2、交换类排序:通过交换,让一个记录排在他最终的位置上
    例如:冒泡排序、快速排序
    3、选择类排序
    例如:简单选择排序、堆排序
    4、归并类排序
    例如:二路归并排序
    5、基数类排序

插入类排序

直接插入排序

直接插入排序执行流程

049(有序)  38 65 97 79 13 27 49*
138 49(有序)  65 97 79 13 27 49*
238 49 65(有序)  97 79 13 27 49*
...     

算法实现

    public int[] insertSort(int[] array){
        for(int i=1;i<array.length;i++)//第0位独自作为有序数列,从第1位开始向后遍历
        {
            if(array[i]<array[i-1])//0~i-1位为有序,若第i位大于i-1位,继续寻位并插入,否则认为0~i位也是有序的,忽略此次循环,相当于continue
            {
                int temp=array[i];//保存第i位的值
                int j;
                for(j = i-1; j>=0 && temp<array[j];j--)//从第i-1位向前遍历并移位,直至找到小于第i位值停止
                {
                    array[j+1]=array[j];

                }
                array[j+1]=temp;//插入第i位的值
            }
        } 

算法性能
最坏情况下时间复杂度:这个序列都是逆序的情况,时间复杂度为O(n平方)
最好情况下时间复杂度:这个序列有序,O(n)
平均时间复杂度O(n平方)
稳定性:稳定

折半插入排序
前提:序列已经有序
执行流程:折半查找位置 + 插入
算法性能:与直接插入排序一样
希尔排序
1、概念:希尔排序又叫缩小增量排序,本质上还是一种插入排序。他首先不断通过缩小增量的方式将带排序的序列划分为几个子序列,对这些子序列进行直接插入排序,使这个序列整体基本有序,最后再进行一次直接插入排序
2、缩小增量的方式:以增量5分割序列、以增量3分割序列、以增量1分割序列(即直接插入排序)
3、执行流程
以增量5分割序列,得到如下子序列

原始序列:49 38 65 97 79 13 27 49* 55 04
子序列一:49             13 
子序列二:   38             27
子序列三:        97          49*
子序列四:           79              04
则第一次希尔排序结果:13 27 49* 04 49 38 97 79  

3、性能分析:平均时间复杂度为nlog2n(记住即可) + 不稳定

交换类排序

冒泡排序
1、算法介绍:冒泡排序使相邻元素间的比较和交换,每一次冒泡排序都会将最大的那个元素交换到最后
2、算法流程:

原序列:5 6 7 2 8 6 1
则一趟冒泡排序的执行流程为:5 6 2 7 6 1 8

3、算法实现

    public void sort(int[] a) {
        int temp = 0;
        for (int i = a.length - 1; i > 0; --i) {
            for (int j = 0; j < i; ++j) {
                if (a[j + 1] < a[j]) {
                    temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                }   
            }            
        }
    }

4、算法分析:
时间复杂度:
最坏情况下:逆序:O(n平方)
最好情况下:有序:O(n)
平均时间复杂度:O(n平方)

快速排序
1、算法介绍:快速排序将第一个元素作为枢纽值,其他值与这个枢纽值做对比,比它小的值放一边,比他大的值放另一边
2、执行流程
以第一个元素为枢纽

原始序列:
49(i) 38 65 97 79 13 27 49*(j)
②先从右边开始,找一个第一小于枢纽的值27,与枢纽值交换
27(i) 38 65 97 79 13 49(j) 49*
③再从左边开始,找一个第一个大于枢纽的值65,与枢纽值交换
27 38 49(i) 97 79 13 65(j) 49*
...
最终i == j时一趟快速排序结束
27 38 13 49(i)(j) 97 79 65 49*

最后再用递归对子序列进行快速排序

3、算法实现

public void sort(int arr[],int low,int high) {
    int l=low;
    int h=high;
    int povit=arr[low];

    while(l<h) {
        while(l<h&&arr[h]>=povit) {
            h--;
        }
        if(l<h){
            int temp=arr[h];
            arr[h]=arr[l]; 
            arr[l]=temp;
            l++;
        }

        while(l<h&&arr[l]<=povit) {
            l++;
        }
        if(l<h) {
            int temp=arr[h];
            arr[h]=arr[l];
            arr[l]=temp;
            h--;
        }
    }
    if(l>low)sort(arr,low,l-1);
    if(h<high)sort(arr,l+1,high);
}

4、性能分析
时间复杂度:
最坏情况下时间复杂度:越接近有序,O(n的平方)
最好情况下时间复杂度:越无需,O(nlog2n)
平均:O(nlog2n)
递归—》压栈

选择类排序

简单选择排序
1、算法介绍,从头开始扫描。选择最小的元素与第一个元素做交换(要与直接插入排序作对比)
2、执行流程

原始序列:8 5 9 7 4 1 2 3 
第一趟选择:1  8 5 9 7 4 2 3 
第二趟排序:1 2  8 5 9 7 4 3 
...

3、算法实现

void select_sort(int*a,int n)
{
    register int i,j,min,t;
    for(i=0;i<n-1;i++)
    {
        min=i;//查找最小值
        for(j=i+1;j<n;j++)
            if(a[min]>a[j])
                min=j;//交换
        if(min!=i)
        {
            t=a[min];
            a[min]=a[i];
            a[i]=t;
        }
    }
}

算法时间复杂度:都是O(n平方)

堆排序
1、算法介绍
可以把堆看成是完全二叉树的数据结构,且这颗二叉树满足:父结点的值大于(或小于)孩子结点的值,这样的堆称为大顶堆,因此可以将原始序列构造成一个大顶堆,堆的根结点即为最大的元素,输出后将剩下的元素继续构造成大顶堆,这样就能实现排序了。
2、执行流程
①将原始序列变为对应的二叉树
②从最后一个非叶结点开始,与孩子结点比较,调整成大顶堆
③输出根节点,让最后一个叶结点与根结点位置互换,将剩下的结点继续构造成大顶堆。(只有这个与根结点交换的叶结点不符合堆的要求,因此只要调整这个结点即可)
3、性能分析
时间复杂度都为O(nlog2n),

二路归并排序
1、算法介绍:元素两两归并
2、执行流程

2 5 9 7 6 4 3 8
二路归并排序:{2, 5}{7, 9}{4, 6}{3,8}
{2 5 7 9} {3 4 6 8}

3、性能分析
时间复杂度都为O(nlog2n)

基数排序
1、算法介绍:基数排序的思想是多关键字排序
2、算法流程:

原始序列:278 063 390 589 184 505 296 008 083
最低位先:390 063 303 184 505 196 278 008 589
十位次之,但是要在最低位先的基础上
        303 505 008 063 278 184 589 390 196
百位最后,但是要在十位的基础上
        008 063 187 196 178 303 390 505 589 

性能分析:不重要

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值