数据结构排序算法总结

本文详细介绍了几种经典的排序算法,包括冒泡排序、快速排序、堆排序、直接插入排序、希尔排序和归并排序。每种排序算法都阐述了其思想、时间复杂度、空间复杂度和稳定性,并提供了相应的伪代码实现。这些排序算法在实际编程中有着广泛的应用。

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

       基本概念:

1、  排序:按照一定的关键字,将一个序列排列成想要得到的一个新的序列。

2、  内部排序和外部排序:整个排序过程完全在内存中进行,叫做内部排序。数据量较大需要借助外部存储设备才能完成,叫做外部排序。

3、  主关键字和此关键字:

4、  排序的稳定性:对于相同的元素来说,在排序之前和之后的书讯是一样的,那么这种排序就是稳定的排序,如果顺序发生了变化,那么就是不稳定排序。



(1)冒泡排序


1、  思想:反复扫描待排序序列,在扫描的过程中顺次比较相邻的两个元素的大小,若逆序就交换位置。第一趟,从第一个数据开始,比较相邻的两个数据,(以升序为例)如果大就交换,得到一个最大数据在末尾;然后进行第二趟,只扫描前 n-1 个元素,得到次大的放在倒数第二位。以此类推,最后得到升序序列。如果在扫描过程中,发现没有交换,说明已经排好序列,直接终止扫描。所以最多进行 n-1 趟扫描。

2、   时间复杂度:T(n) = O(n²)

3、   空间复杂度:S(n) = O(1)

4、   稳定性:稳定排序  

     
    static void bubbleSort(int array[], int length) {
        for (int i = 0; i < length - 1; i++) {
            for (int j = 0; j < length - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
            print(array, length);
        }
    }



(2)快速排序


1、   思想:冒泡排序一次只能消除一个逆序,为了能一次消除多个逆序,采用快速排序。以一个关键字为轴,从左从右依次与其进行对比,然后交换,第一趟结束后,可以把序列分为两个子序列,然后再分段进行快速排序,达到高效。

2、   时间复杂度:平均T(n) = O(nn),最坏O(n²)

3、   空间复杂度:S(n) = O(n)

4、   稳定性:不稳定排序。{3 2 2}


    static void quickSort(int array[], int left, int right) {
        if (left >= right)
            return;
        int pivot = array[left];
        int i = left;
        int j = right;
        while (i != j) {
            while (array[j] >= pivot && j > i)
                j--;
            while (array[i] <= pivot && i < j)
                i++;
            if (i < j) {
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
        array[left] = array[i];
        array[i] = pivot;


        quickSort(array, left, i - 1);
        quickSort(array, i + 1, right);
    }


(3)堆排序


1、   思想:把待排序记录的关键字存放在数组r[1…n]中,将r看成是一刻完全二叉树的顺序表示,每个节点表示一个记录,第一个记录r[1]作为二叉树的根,一下个记录r[2…n]依次逐层从左到右顺序排列,任意节点r[i]的左孩子是r[2i],右孩子是r[2i+1],双亲是r[i/2向下取整]。然后对这棵完全二叉树进行调整建堆。

2、   时间复杂度:T(n) = O(nn)

3、   空间复杂度:S(n) = O(1)

4、   稳定性:不稳定排序。{5 5 3}


    static void adjustHeap(int array[], int parent, int length, bool large) {
        int pivot = array[parent]; //保存当前父节点
        int child = 2 * parent + 1; //获取左孩子
        while (child < length) {
            if (large) {
                //大顶堆
                //如果有右孩子,且右孩子大于左孩子,选取有孩子节点
                if (child + 1 < length && array[child] < array[child + 1])
                    child++;
                // 如果父节点的值已经大于孩子节点的值,则直接结束
                if (array[parent] >= array[child])
                    break;
            } else {
                //如果有右孩子,且右孩子小于左孩子,选取右孩子节点
                if (child + 1 < length && array[child] > array[child + 1])
                    child++;
                //如果父节点的值已经小于孩子节点的值,则直接结束
                if (array[parent] < array[child])
                    break;
            }
            //把孩子节点的值赋给父节点
            array[parent] = array[child];
            //选取孩子节点的左孩子节点,继续向下筛选
            parent = child;
            child = child * 2 + 1;
       array[parent] = pivot; 
        }
    }
    /*
     * 初始化堆
     * 调整之后,第一个元素为序列的极值
     */
    static void buildHeap(int array[], int length, bool large) {
        for (int i = (length - 1) / 2; i >= 0; --i)
            adjustHeap(array, i, length, large);
    }


(4)直接插入排序


1、   思想:最基本的插入排序,将第i个插入到前i-1个中的适当位置。

2、   时间复杂度:T(n) = O(n²)

3、   空间复杂度:S(n) = O(1)

4、   稳定性:稳定排序。循环条件while(r[0].key< r[j].key)保证的。


    static void directInsertSort(int array[], int length) {
        //升序版本
        for (int i = 1; i < length; i++) {
            if (array[i] < array[i - 1]) {                //找到小数
                int j = i - 1;
                int pivot = array[i];                //复制小数为哨兵元素
                array[i] = array[i - 1];                //先进行一次后移
                while (pivot < array[j] && j >= 0) {                //寻找小数插入位置
                    array[j + 1] = array[j];
                    j--;
                }
                array[j + 1] = pivot;
            }
        }
    }


(5)希尔排序


1、   思想:又称缩小增量排序法。把待排序序列分成若干较小的子序列,然后逐个使用直接插入排序法排序,最后再对一个较为有序的序列进行一次排序,主要是为了减少移动的次数,提高效率。原理应该就是从无序到渐渐有序,要比直接从无序到有序移动的次数会少一些。

2、   时间复杂度:O(n1.5次方)

3、   空间复杂度:O(1)

4、   稳定性:不稳定排序。{2,4,1,2}21一组42一组,进行希尔排序,第一个2和最后一个2会发生位置上的变化。


    static void shellSort(int array[], int length) {
        int gap = length / 2;
        while (gap >= 1) {
            //距离间隔gap为一组,遍历所有组
            for (int i = gap; i < length; i++) {
                if (array[i] < array[i - gap]) {
                    int j = i - gap;
                    int x = array[i];
                    array[i] = array[j];
                    //寻找x在当前序列上的插入点
                    while (x < array[j] && j >= 0) {
                        array[j + gap] = array[j];
                        j -= gap;
                    }
                    array[j + gap] = x;
                }
            }
            print(array, length);
            gap /= 2;
        }
    }



(6)  归并排序:

1、   思想:假设初始序列右n个记录,首先将这n个记录看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2向上取整 个长度为2n为奇数时,最后一个序列的长度为1)的有序子序列。在此基础上,在对长度为2的有序子序列进行两两归并,得到若干个长度为4的有序子序列。如此重复,直至得到一个长度为n的有序序列为止。

2、   时间复杂度:T(n) = O(nn)

3、   空间复杂度:S(n) = O(n)

4、   稳定性:稳定排序。


    static void mergeSort(int array[], int helper[], int left, int right) {
        if (left >= right)
            return;
        int mid = (left + right) / 2;
        mergeSort(array, helper, left, mid);
        mergeSort(array, helper, mid + 1, right);


        int helperLeft = left;
        int helperRight = mid + 1;
        int cur = left;
        for (int i = left; i <= right; i++) {
            helper[i] = array[i];
        }
        while (helperLeft <= mid && helperRight <= right) {
            if (helper[helperLeft] <= helper[helperRight])
                array[cur++] = helper[helperLeft++];
            else
                array[cur++] = helper[helperRight++];
        }
        while (helperLeft <= mid)
            array[cur++] = helper[helperLeft++];
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值