插入排序
在有序序列中插入一个值(tmp),(只有一个数据也是有序的),从有序序列的末端开始比较,比它小,就把这个数据往后放,依次去比,直到比到第一个数。
走完一趟 有序数组的大小就会增长一个。
void InsertSort(vector<int>& a)
{
//[0,end]是有序的 现在插入的是 end+1这位数据
//从后向前依次比较 查看插入位置
for (int i = 0; i < a.size() - 1; i++)
{
//单趟
int end=i;
int tmp = a[end + 1];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + 1] = a[end];
end--;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
希尔排序
由于插入排序在数据接近有序下的时间复杂是很低的,所以采用预排序,干涉一下数据。将数据每间隔gap个分为一组,先将这些数据采用插入排序。然后最后再使用gap==1时,即直接插入排序完成排序。
void ShellSort(vector<int>& a)
{
int gap = a.size();
while (gap > 1)
{
gap = gap / 3 + 1;//保证gap最少是1
for (int i = 0; i + gap < a.size(); i++)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}
}
选择排序
每次遍历选择一个最大的和一个最小的 插入在数组的begin处和end处,每插入一次之后begin++,end-- 直到二者相遇,则全部排序完成。
void SelectSort(vector<int>& a)
{
if (a.empty()) return;
int n = a.size();
//begin 和 end是已经确定好排序的下标
int begin = 0, end = n - 1;
while (begin < end)
{
int mini = begin, maxi = end;
for (int i = begin; i <= end; i++)
{
if (a[mini] > a[i])
{
mini = i;
}
if (a[maxi] < a[i])
{
maxi = i;
}
}
swap(a[begin], a[mini]);
if (maxi == begin)
{
maxi = mini;
}
swap(a[end], a[maxi]);
++begin;
--end;
}
}
堆排序
先将数据导入数组中,找到最后一个非叶节点,从它开始向下调整,自后向前。于是得到了一个大堆或者小堆。
这里以大堆为例。然后将堆顶的数据和堆尾的数据进行交换,并将堆尾的数据剔除排序区间。从堆顶再次进行向下调整,可以使得第二大的数称为堆顶。
再次交换堆顶和堆尾,并将堆尾的数据剔除排序区间...
//堆排序
void AdjustDown(vector<int>& a ,int length,int starti)
{
//找孩子
int child = starti * 2 + 1;
//最差结果就是把最后一个数也调整了
while (child < length)
{
if (child + 1 < length && a[child] < a[child + 1]) child++;
if (a[child] > a[starti])
{
swap(a[child], a[starti]);
starti = child;
child = starti * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(vector<int>& a)
{
int n = a.size();
int start = (n - 1 - 1) / 2;//找到最后一个非叶节点
//依次向下调整
for (int i = start; i >= 0; i--)
{
AdjustDown(a,n,i);
}
//建成了一个大堆 要弄成升序
int end = n - 1;
while (end > 0)
{
swap(a[0], a[end]);
AdjustDown(a, end, 0);
--end;
}
}
冒泡排序
跟前一个比 你比我大 咱俩就交换 每过一轮就有一个当前的最大的值被换到数列尾,那么就可以少遍历一次。
void BubbleSort(vector<int>& a)
{
int n = a.size();
for (int j = 0; j < n - 1; j++) //轮次 4个数最多走三轮 剩下一个就自己确定了
{
int change = false;
for (int i = 1; i < n - j; i++)
{
if (a[i-1] > a[i])
{
swap(a[i - 1], a[i]);
change= true;
}
}
if (!change) break; //如果一轮遍历下来 没有交换 就证明已经有序了
}
}
快速排序
[left,right] 是一个左闭右闭区间
void QuickSort(int arr[], int left, int right)
{
if (left >= right) return;
int key = arr[(left + right) / 2];//区间中间的那个值做key
int i = left - 1;
int j = right + 1;
while (i < j)
{
//左找大
do
{
i++;
} while (arr[i] < key);
//右找小
do
{
j--;
} while (arr[j]>key);
if (i < j)
{
swap(arr[i], arr[j]);
}
}
QuickSort(arr, left, j);
QuickSort(arr, j+1, right);
}
其他版本
// 快速排序hoare版本
void PartSort1(int* a, int left, int right)
{
int begin = left; int end = right;//left 和 right会随着程序改变,找两个变脸记录初始位置
if (begin >= end)
{//区间不存在 就不用排序了
return;
}
//左边做key 右边向左找小,左边向右找大
int keyi = left;
while (left < right)
{
while (left < right && a[right] >= a[keyi])
{
right--;
}
while (left < right && a[left] <= a[keyi])
{
left++;
}
//到达此位置 表示找到了大和小
swap(&a[left], &a[right]);
}
//到达此位置 表示左右相遇 a[left] 去和a]keyi]交换
swap(&a[left], &a[right]);
keyi = left;// xxxx keyi xxxx
PartSort1(a, begin, keyi - 1);
PartSort1(a, keyi + 1, end);
}
// 快速排序挖坑法
void PartSort2(int* a, int left, int right)
{
int begin = left; int end = right;//left 和 right会随着程序改变,找两个变脸记录初始位置
if (begin >= end)
{//区间不存在 就不用排序了
return;
}
int holei= left;//坑的坐标
int key = a[begin];//存储坑的数据
while (left < right)
{
while (left < right && a[right] >= a[holei])
{
right--;
}
//自身成为洞
a[holei] = a[right];//洞的数据不重要,直接赋值即可
holei = right;//更新洞的坐标
while (left < right && a[left] <= a[holei])
{
left++;
}
a[holei] = a[left];
holei = left;
//到达此位置 表示找到了大和小
swap(&a[left], &a[right]);
}
//到达此位置 表示左右相遇 a[left] 去和a]keyi]交换
a[left] = key;//存储的第一个洞的值
holei = left;// xxxx holei xxxx
PartSort1(a, begin, holei - 1);
PartSort1(a, holei + 1, end);
}
// 快速排序前后指针法
void PartSort3(int* a, int left, int right)
{
int begin = left; int end = right; int keyi = begin;
if (begin <= end)
{
return;
}
// prev cur a[cur]和a[keyi]比较 小于时 prev++ 交换 cur 和 prev.cur++;
int prev = begin; int cur = prev + 1;
while (cur <= end)
{
if (a[cur] < a[keyi])
{
++prev;
swap(&a[cur], &a[prev]);
++cur;
}
}
//cur越界了
swap(&a[prev], &a[keyi]);
keyi = prev;// xxxx keyi xxxxx
PartSort3(a, begin, keyi - 1);
PartSort3(a, keyi + 1, end);
}