1、冒泡排序:稳定
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的元素列,一次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。
基本思想: (1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。
(2)对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
(3)针对所有的元素重复以上的步骤,除了最后一个。 (4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
void BubbleSort(int *a, int n) {
for (int i = 0; i < n - 1; i++) //外层循环控制趟数,总趟数为len-1
for (int j = 0; j < n - 1 - i; j++) //内层循环为当前i趟数 所需要比较的次数
if (a[j] > arr[j + 1])
Swap(arr[j], arr[j + 1]);
}
2、快速排序(最重要:必须掌握):分治
(1)左右下标寻找法
//方法一:左右下标寻找法
int partSort1(int* a,int left,int right)
{
int key = a[right];
int begin = left;
int end = right; //int end = right-1的反例为:1 2 3 4 5 6 7 8 9
while (begin < end)
{
while (begin <end && a[begin] <= key) // 从左到右依次寻找比key大的值
{
begin++;
}
while (begin < end && a[end] >= key) //从右到左依次寻找比key小的值
{
end--;
}
// 找到之后交换
if (begin < end)
Swap(a[begin],a[end]);
}
// begin只会有两个位置:(1)a[begin]>key; (2)a[begin]就是right(key所在的位置)
Swap(a[begin], a[right]);
// 返回begin;begin就是哨兵数所在的下标
return begin;
}
void QuickSortRecursion(int* a, int left, int right)
{
//left == right时表示区间内只有一个数;left>right时表示区间内已经没有数了
if (left >= right)
return;
// 排序结束条件:[left,right)之间数目只剩0个或1个
// [left, div)这里面的数都比div小
// (div, right] 这里面的数都比div大
int div = partSort1(a, left, right);
QuickSortRecursion(a, left, div - 1);
QuickSortRecursion(a, div + 1, right);
}
void QuickSort(int *a, size_t n)
{
//递归
QuickSortRecursion(a, 0, n - 1);
}
(2)挖坑法
// 方法二:挖坑法
int partSort2(int* a, int left, int right)
{
int key = a[right];
int begin = left;
int end = right;
while (begin < end)
{
while (begin < end && a[begin] <= key)
begin++;
a[end] = a[begin];
while (begin < end && a[end] >= key)
end--;
a[begin] = a[end];
}
a[begin] = key; //将key填到这个坑
return begin; //哨兵所在的下标
}
(3)前后下标
基本思想:
定义两个指针,prev和cur,再定义key的值,cur指针从left开始,遇到比key大的就过滤掉,比key小的,就停下来,prev++,判断prev和cur是否相等,如果不相等,就将两个值进行交换,最后一趟排序下来,比key小的,都留在了key的左边,比key大的都在key的右边。
int partSort3(int*a, int left, int right)
{
int key = a[right - 1];
int cur = left;
int pre = cur - 1;
while (cur < right)
{
if (a[cur] < key&& ++pre != cur)
{
Swap(a[cur], a[pre]);
}
cur++;
}
if (++pre != right)
{
Swap(a[pre], a[right - 1]);
}
return pre;
}
优化:
三数取中法:
int GetMidIndex(int *a,int left,int right)
{
int mid = left + (right - left) / 2;
if (a[left] < a[mid])
{
if (a[left]>a[right])
{
return left;
}
else if (a[mid] > a[right])
{
return right;
}
else
{
return mid;
}
}
else
{
if (a[mid] > a[right])
{
return mid;
}
else if (a[left] > a[right])
{
return right;
}
else
{
return left;
}
}
}
int partSort(int *a, int left, int right)
{
int key = 0;
int cur = left;
int firstBigger = left;
int index = GetMidIndex(a,left,right);
Swap(a[index],a[right-1]);
key = a[right - 1];
while (cur < right)
{
if (a[cur] < key)
{
Swap(a[firstBigger], a[cur]);
firstBigger++;
}
cur++;
}
Swap(a[firstBigger],a[right-1]);
return firstBigger;
}