题外话: 加油!!
1.什么是交换排序?
- 回想一下初中时期,上学第一天,班主任让所有的同学按高矮站成2排,男生1排,女生1排;
- 如果身高差大还好,对于身高差不大的同学来说,很容易排错位置,全班只有A和B同学的位置错了;
- 此时班主任会过来说:“A,你和B换一下位置”。
- 此刻,整个班级的队伍,遵循从高到矮的顺序了。
- 过程中,两个同学互相交换位置,不会影响到第三个同学的操作,就是交换排序。
2.冒泡排序
- 什么是冒泡排序?
- 相邻两个元素比较大小,并根据大小关系互相交换位置;
- 整个过程像一个泡泡,逐渐浮向水面一样。
- 代码实现(普通版本)
/// <summary>
/// 普通的冒泡排序
/// </summary>
/// <param name="pArray">普通一数组</param>
static public void NBubbleSort(int[] pArray)
{
int temp;
//本层循环只是确保循环够次数,i本身不做元素索引用
for (int i = 1; i < pArray.Length; i++)
{
//本层循环每次都会减少上限;
//因为每次循环结束后,最后n个元素,一定是最大的,不需要再遍历到了。
for (int j = 0; j < pArray.Length - i; j++)
{
if (pArray[j] > pArray[j + 1])
{
temp = pArray[j];
pArray[j] = pArray[j + 1];
pArray[j + 1] = temp;
}
}
}
}
普通版本:
冒泡排序有一个特点,即在“浮出”一个又一个相对较大的元素时,也会一定程度上理顺其他元素的大小关系。
优化思路: 如果在某一次“浮出”元素的过程中,没有任何一个元素发生交换,就说明整个队列的排序已经完成,可以结束循环了。
- 优化版代码
/// <summary>
/// 优化后的冒泡排序
/// </summary>
/// <param name="pArray">普通一数组</param>
static public void BBubbleSort(int[] pArray)
{
int temp;
bool flag;
//本层循环只是确保循环够次数,i本身不做元素索引用
for (int i = 1; i < pArray.Length; i++)
{
flag = false;
//本层循环每次都会减少上限;
//因为每次循环结束后,最后n个元素,一定是最大的,不需要再遍历到了。
for (int j = 0; j < pArray.Length - i; j++)
{
if (pArray[j] > pArray[j + 1])
{
flag= true;
temp = pArray[j];
pArray[j] = pArray[j + 1];
pArray[j + 1] = temp;
}
}
if (!flag)
{
break;
}
}
}
- 时间复杂度:
- 最好的情况:O(n)
- 最差的情况:O(n^2)
- 平均:O(n^2)
- 空间复杂度:
- O(1)
- 算法稳定性:
- 稳定
3.快速排序
- 什么是快速排序?
- 从数据中随便拿出一个元素x,其他所有元素与x做比较;
- 比x小的,统统放到x左边,比x大的,放到x右边;
- 由x又分割了两个数据表,再对左右两边做步骤1、2;
- 递归,完成整个数据表的排序。
- 代码实现
/// <summary>
/// 快速排序
/// </summary>
/// <param name="pArray">索引从1开始有效的数组</param>
/// <param name="start"></param>
/// <param name="end"></param>
static public void QKSort(int[] pArray, int low, int high)
{
if (low < high)
{
//确定中心点位置
int pivot = Partition(pArray, low, high);
//对左右子集递归
QKSort(pArray, low, pivot - 1);
QKSort(pArray, pivot+1, high);
}
}
static public int Partition(int[] pArray, int low, int high)
{
//设置哨兵元素
pArray[0] = pArray[low];
//双指针法
while (low < high)
{
//从后向前遍历,寻找小于中心点的元素,并给到low
while (high > low && pArray[high] >= pArray[0])
high--;
pArray[low] = pArray[high];
//从前向后遍历,寻找大于中心点的元素,给到high
while (low < high && pArray[low] < pArray[0])
low++;
pArray[high] = pArray[low];
}
//复位哨兵元素
pArray[low] = pArray[0];
return low;
}
- 时间复杂度:
- 最好的情况:O(nlogn)
- 最坏的情况:O(n^2)
- 平均:O(nlogn)
- 空间复杂度:
- 最好:O(logn)
- 最坏:O(n)
- 算法稳定性:
- 不稳定。
结束语: 加油!!