排序算法

(一)冒泡排序

原理: 相邻两元素进行两两比较,将值大元素放在后面,每趟排序都能获得一个当前剩余元素的最大值。所以比较n-1次即可排序完成。
时间复杂度: O(n²),比较n-1趟每趟比较n-i个元素 (n-1)(n-i);最优时为顺序即已经排好了,只比较n-1次所以最优时间复杂度为O(n),如果不知道是否排序完成则仍为O(n²);最坏时为逆序3(n-1)(n-i),多了交换代码产生的时间仍为O(n²)。
空间复杂度: O(1),由交换时的临时变量产生,最好时不用交换为0,也可以采用 a = a + b; b = a - b; a = a - b;的方式降到0。
稳定性: 稳定
代码如下:

public class BubbleSorting : MonoBehaviour
{
    private int[] m_Array = new int[] { 12, 5, 67, 42, 6, 62, 8, 26, 2, 3 };
    private int m_Temp = 0; // 将临时变量提出来,否则会在循环中频繁创建,影响空间复杂度
    private int m_Flag = 1; // 排序是否完成的标志位,1表示排序完成
    private void Awake()
    {
        int count = m_Array.Length;
        for (int i = 0; i < count; i++, m_Flag = 1) // 比较n-1趟
        {
            for (int j = 0; j < count - i - 1; j++) // 每趟比较剩余的n-i个元素
            {
                if (m_Array[j] > m_Array[j + 1])
                {
                    m_Temp = m_Array[j + 1];
                    m_Array[j + 1] = m_Array[j];
                    m_Array[j] = m_Temp;
                    m_Flag = 0; // 该趟存在交换说明排序没有完成
                }
            }
            if (m_Flag == 1)
            {
                break;
            }
        }
        for (int i = 0; i < count; i++)
        {
            Debug.Log(m_Array[i]);
        }
    }
}

(二)选择排序

原理: 每次大循环将该组数中最小的元素放在前面,内次循环负责找出该组数中最小的数
时间复杂度: O(n²)
空间复杂度: O(1),由交换时的临时变量产生
稳定性: 不稳定,当存在相等的数时会改变先后顺序
代码如下:

public class SelectionSorting : MonoBehaviour
{
    private int[] m_Array = new int[] { 12, 5, 67, 42, 6, 62, 8, 26, 2, 3 };
    private int m_Temp, m_Min = 0; // 将临时变量提出来,否则会在循环中频繁创建,影响空间复杂度
    private void Awake()
    {
        int count = m_Array.Length;
        for (int i = 0; i < count - 1; i++)
        {
            m_Min = i;
            for (int j = i + 1; j < count; j++)
            {
                if (m_Array[m_Min] > m_Array[j])
                {
                    m_Min = j; // 记下最小值所在的索引
                }
            }
            m_Temp = m_Array[m_Min];
            m_Array[m_Min] = m_Array[i];
            m_Array[i] = m_Temp;
        }

        for (int i = 0; i < count; i++)
        {
            Debug.Log(m_Array[i]);
        }
    }
}

(三)快速排序

原理: 分治法,选定一个基准,然后从后往前和从前往后进行比较,比较完成后比基准大的值就都排在了基准的右边,比基准小的值就都排在了基准值的左边,注意过程中基准值所在的索引位置是在变动的

  1. 选定一个基准值(可以是随机的,网上的例子一般取第一个值)
  2. 挖坑法,一开始坑在基准值所在索引处,从后往前遍历遇到第一个比基准值小的将值赋到基准值所在索引,将坑转移到这个比基准值小的值的索引处,注意坑的位置变化
  3. 从前往后遍历遇到第一个比基准值大的将值赋到坑的位置,同时改变坑的位置到这个比基准值大的值处
  4. 循环2,3步,直到从后往前遍历和从前往后遍历到同一个索引处,此时将一开始选中的基准值赋到此处,到此基准值左侧全部是比基准值小的值,基准值右侧全部是比基准值大的值
  5. 再将基准值索引左侧的数组按此方法排序,右侧数组按此方法排序,递归下去直到剩余数组只包含一个值,则整个数组排序完成
    时间复杂度: Ο(nlogn) 最坏O(n²)
    空间复杂度: 最优每一次都平分数组的情况O(logn),最差的情况下空间复杂度为:O( n ) 退化为冒泡排序的情况
    稳定性: 不稳定,当存在相等的数时会改变先后顺序
    代码如下:
public class QuickSorting : MonoBehaviour
{
    private int[] m_Array = { 49, 38, 65, 97, 76, 13, 27 };
    private int m_Count = 0;
    private void Awake()
    {
        m_Count = m_Array.Length;
        QuickSort(m_Array, 0, m_Count - 1);
        for (int i = 0; i < m_Count; i++)
        {
            Debug.Log(m_Array[i].ToString());
        }
    }
    private void QuickSort(int[] array, int left, int right)
    {
        if (left < right) // 常见错误:不加这个判断
        {
            int index = SortUnit(array, left, right);
            QuickSort(array, 0, index - 1);
            QuickSort(array, index + 1, right); // 常见错误:QuickSort(array, index + 1, m_Count - 1)
        }
    }
    private int SortUnit(int[] array, int left, int right)
    {
        int pivot = array[left];
        while (left < right)
        {
            while (right > left && array[right] >= pivot) // 常见错误:pivot写成array[left]
            {
                right--;
            }
            array[left] = array[right];
            while (left < right && array[left] <= pivot) // 常见错误:pivot写成array[right]
            {
                left++;
            }
            array[right] = array[left];
        }
        array[left] = pivot; // 此时left == right
        return left;
    }
}

(四)堆排序

参考我的这篇文章 数据结构之堆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿斯提尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值