快速排序
/*
算法思想:在参加排序的序列中任意选择一个元素(通常称为分界元素或基准元素),把小于或等于
分界元素的所有元素都移到分界元素的前面,把大于分界元素的所有元素都移到分界元素的后面,
这样,当前参加排序的序列就被划分成前后两个子序列,其中前一个子序列中的所有元素都小于后
一个子序列的所有元素,并且分界元素正好处于排序的最终位置上。然后分别对这两个子序列递归
地进行上述排序过程,直到所有元素都处于排序的最终位置上,排序结束。
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
//输出结果
void printData(vector<int> a);
//将 pivot左边的数都小于他,右边的数都大于他
int Partition(vector<int>& a, int low, int high)
{
int pivot;
//其实为了方便直接用第一个数做枢纽值很不好
pivot = a[low];
//从线性表的两端交替地向中间扫描
while (low < high)
{
while (low < high && a[high] >= pivot) high--;
//比枢纽值小,就把他放到枢纽值左边
a[low] = a[high];
while (low < high && a[low] <= pivot) low++;
//比枢纽值大,就把他放到枢纽值右边
a[high] = a[low];
}
// 此时, pivot左边的数据都小于他,右边的数据都大于他
a[low] = pivot;
//返回枢纽值位置
return low;
}
void Qsort(vector<int>& a, int low, int high)
{
int pivotloc;
if (low < high)
{
//设置pivot值,然后排序, 使得 pivot左边的数都小于他,pivot右边的数都大于他,
//返回排序后pivot的位置 pivotloc, 然后再对其 两边的数据 递归排序
pivotloc = Partition(a, low, high);
//枢纽值(pivot)左边的数都小于 pivot, 排序所有小于pivot的值
Qsort(a, low, pivotloc - 1);
//pivot右边的数都大于pivot, 排序所有大于pivot的值
Qsort(a, pivotloc + 1, high);
}
}
//启动程序
void QuickSort(vector<int>& a, int size)
{
//设置排序的区间
Qsort(a, 0, size - 1);
printData(a);
}
void printData(vector<int> a)
{
for (const auto& e : a) {
cout << e << " ";
}
cout << endl;
}
int main()
{
vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12, 44, 23, 34};
unsigned n = a.size();
//插入排序
QuickSort(a, n);
return 0;
}
堆排序
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
void printData(vector<int> a)
{
for (const auto& e : a) {
cout << e << " ";
}
cout << endl;
}
//调整为大顶堆
void HeapAdjust(vector<int>& a, int low, int high)
{
int child;
int tmp;
//tmp: 父亲结点; 左结点的索引 < n ; 继续 判断孩子结点
// 2 * i : 获得左孩子结点索引
for (tmp = a[low]; low * 2 < high; low = child)
{
child = low * 2; //获得左孩子结点索引
//如果孩子结点索引 尚未越界, 且 左孩子结点 小于 右孩子 结点
//就获得右孩子结点索引
if (child != high - 1 && a[child] < a[child + 1]) {
child++;
}
if (tmp < a[child]) { //父亲 < 孩子
a[low] = a[child]; //孩子 替换 父亲结点
}
else {
break;
}
}
a[low] = tmp; //将父亲结点 插入 到比他大的 孩子结点位置.
}
//没有使用传引用,不改变 a
void HeapSort(vector<int>& a, int n)
{
//建立大顶堆
for (int i = n / 2; i >= 0; i--)
{
HeapAdjust(a, i, n);
}
for (int j = n - 1; j > 0; j--)
{
swap(a[0], a[j]);
//将 a[1..i] 重新调整为大顶堆
HeapAdjust(a, 0, j);
}
printData(a);
}
int main()
{
vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12, 44, 23, 34};
unsigned n = a.size();
//插入排序
HeapSort(a, n);
return 0;
}
不懂可以看这个: https://www.cnblogs.com/0zcl/p/6737944.html
归并排序
#include <iostream>
#include <cstring>
using namespace std;
int test[100] = { 0 };
void Merge(int *test, int lo, int mid, int hi);
void MergeSort(int *test, int lo, int hi) {
if (hi - lo < 2) return;
int mid = (lo + hi) >> 1;
MergeSort(test, lo, mid); //对前半段排序
MergeSort(test, mid, hi); //对后半段排序
Merge(test, lo, mid, hi); //归并
}
//归并---O(nlogn), T(n) = 2T(n/2) + O(n)
void Merge(int *test, int lo, int mid, int hi) {
//A用来存放合并后的向量,B,C进行比较(前后子向量比较)
int *A = test + lo; //合并后的向量A[0,hi-lo) = int s[lo,hi)
int lb = mid - lo;
int *B = new int [lb]; //前子向量 B[0,lb) = int s[lo,mi)
for (int i = 0; i < lb; B[i] = A[i++]); //复制前子向量
int lc = hi - mid;
int *C = test + mid; //后子向量
for (int i = 0, j = 0, k = 0; (j < lb || k < lc);) {
//B[i], C[k]中小者转至A的末尾.
//因为C本来就占据A中,不需要考虑提前耗尽情况
if ((j < lb) && (k >= lc || C[k] >= B[j])) //C[k]已无或不小
A[i++] = B[j++];
if ((k < lc) && (j >= lb || B[j] >= C[k])) //B[k]已无或不小
A[i++] = C[k++];
}
delete[]B;
}
int main()
{
//用来测试 非模板写的 归并排序 算法
int Test[13] = { 1, 5, 2, 3, 6, 8, 9, 10, 13, 12, 4, 7, 11 };
MergeSort(Test, 0, 13);
for (int i = 0; i < 13; i++)
cout << Test[i] << " ";
cout << endl;
return 0;
}
插入排序
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
void printData(vector<int> a)
{
for (const auto& e : a) {
cout << e << " ";
}
cout << endl;
}
//没有使用传引用,不改变 a
void InsertSort(vector<int> a, int n)
{
for (int i = 1; i < n; i++)
{
if (a[i] < a[i - 1]) //当前选择的数 < 前一个数
{ //就把放到前面去
int j = i - 1;
int temp = a[i];
//当前的数跟前面数比较, 一直小,前面的数就一直后移
while (j >= 0 && temp < a[j])
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp;
}
}
printData(a);
}
//折半插入排序, 只是使用折半查找的方法来寻找插入位置
void BinInsertSort(vector<int> a, int n)
{
int low, high, mid, tmp;
for (int i = 1; i < n; i++)
{
tmp = a[i];
low = 0, high = i - 1;
while (low <= high)
{
mid = (low + high) / 2;
if (tmp > a[mid]) {
low = mid + 1;
}
else {
high = mid - 1;
}
}
for (int j = i; j > low; j--) {
a[j] = a[j - 1]; //前移
}
a[low] = tmp;
}
printData(a);
}
int main()
{
vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12};
unsigned n = a.size();
//插入排序
InsertSort(a, n);
//折半插入排序
BinInsertSort(a, n);
return 0;
}
选择排序
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
void printData(vector<int> a)
{
for (const auto& e : a) {
cout << e << " ";
}
cout << endl;
}
//没有使用传引用,不改变 a
void ChooseSort(vector<int> a, int size)
{
int min = 0, i, j;
for (i = 0; i < size - 1; i++)
{
min = i; //此假设为最小值的下标
for (j = min + 1; j < size; j++)
{
if (a[min] > a[j]) {
min = j; //找出当前位置 最小值的下标
}
}
//如果假设的最小的下标改变了,就将最小下标位置元素
//与 i 位置交换,则 i 为当前位置最小的元素
if (i != min) {
swap(a[i], a[min]);
}
}
printData(a);
}
int main()
{
vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12, 44, 23, 34};
unsigned n = a.size();
//插入排序
ChooseSort(a, n);
return 0;
}
冒泡排序
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
void printData(vector<int> a)
{
for (const auto& e : a) {
cout << e << " ";
}
cout << endl;
}
//没有使用传引用,不改变 a
void BubbleSort(vector<int> a, int n)
{
bool ordered;
//外层循环 -- 一共进行比较的趟数( n - 1 )
for (int i = 0; i < n - 1; i++)
{
ordered = true;
//每趟需要比较的次数
//每次循环后,可以依次得到Max,次Max, 次次max......
for (int j = 0; j < n - i - 1; j++)
{
//每次选出 当前位置元素 应当所在的 最大位置, 并交换
if (a[j] > a[j + 1])
{
swap(a[j], a[j + 1]);
//只要交换,则说明交换前,不是有序
ordered = false;
}
}
//一次交换都没有,说明已经没有逆序对,则已经有序,直接退出循环!
if (ordered) {
break;
}
}
printData(a);
}
int main()
{
vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12};
unsigned n = a.size();
//插入排序
BubbleSort(a, n);
return 0;
}