(一)冒泡排序
原理: 相邻两元素进行两两比较,将值大元素放在后面,每趟排序都能获得一个当前剩余元素的最大值。所以比较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]);
}
}
}
(三)快速排序
原理: 分治法,选定一个基准,然后从后往前和从前往后进行比较,比较完成后比基准大的值就都排在了基准的右边,比基准小的值就都排在了基准值的左边,注意过程中基准值所在的索引位置是在变动的
- 选定一个基准值(可以是随机的,网上的例子一般取第一个值)
- 挖坑法,一开始坑在基准值所在索引处,从后往前遍历遇到第一个比基准值小的将值赋到基准值所在索引,将坑转移到这个比基准值小的值的索引处,注意坑的位置变化
- 从前往后遍历遇到第一个比基准值大的将值赋到坑的位置,同时改变坑的位置到这个比基准值大的值处
- 循环2,3步,直到从后往前遍历和从前往后遍历到同一个索引处,此时将一开始选中的基准值赋到此处,到此基准值左侧全部是比基准值小的值,基准值右侧全部是比基准值大的值
- 再将基准值索引左侧的数组按此方法排序,右侧数组按此方法排序,递归下去直到剩余数组只包含一个值,则整个数组排序完成
时间复杂度: Ο(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;
}
}
(四)堆排序
参考我的这篇文章 数据结构之堆