图有误,快排空间复杂度应为O(1),只用了一个临时变量空间,
希尔排序空间复杂度也为O(1),确定好分组后每次进行的是插入排序,也只需要一个temp空间或者直接swap
01冒泡排序
void maopao(int* pt,int n)
{
for (int i = n - 1; i > 0; i--)//找出第i大(小)的数
for (int j = 0; j < i; j++)//在未排序数中依次比较相邻的数,将大的放后面,
if (pt[j] > pt[j + 1])//这样遍历下来最后面的就是未排序数最大(小)的数
{
int temp = pt[j];
pt[j] = pt[j + 1];
pt[j + 1] = temp;
}
for (int i = 0; i < n; i++)
cout << pt[i] << " ";
}
02插入排序
一句话描述:在数组前维护一个有序数组,不断从后面无序数组中的第一个元素插入前面的有序数组
void charu(int* pt, int n)
{
for (int i = 1; i < n; i++)
//将数组分为两部分,每次大循坏给前一部分数量+1.给后一部分数量-1
//每次小循环将后一部分的第一个元素A从后往前依次与前一部分的元素比较,若是从小到大排列,
//当A比被比较元素小时则交换
for (int j = i; j > 0; j--)
{
if (pt[j] < pt[j - 1])
{
int temp = pt[j - 1];
pt[j - 1] = pt[j];
pt[j] = temp;
}
}
for (int i = 0; i < n; i++)
cout << pt[i] << " ";
}
03选择排序
一句话描述:跟打扑克整理手牌一样,也是在数组前维护一个有序数组,然后从后面的无序数组中不断选择出最小的插入到有序数组头部
01.假设第一个数为最小的数
02.从第一个数,寻找真正的最小数,记为min
03.将真正的最小数与第一个数交换位置,并以这个位置为起点重复123步
void xuanze(int* pt, int n)
{
int tem;
for (int i = 0; i < n; i++)
{
int min = pt[i];
int j = i;
int k= i;
for (; j < n; j++)//找到最小元素下标k
if (min > pt[j])
{
min = pt[j]; k = j;
}
tem = pt[i];
pt[i] = pt[k];
pt[k] = tem;//最小元素与头部元素交换位置
}
for(int i=0;i<n;i++)
cout << pt[i]<<" ";
}
04希尔排序
希尔排序
“希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。
一句话描述:将整个数组进行多次分组,分组的间距会越来越小,分成的组的数量会越来越少,每分完一次进行一次插入排序
void ShellSort2(int A[], int n) {
int i, j, k, d, temp;
for (d = n / 2; d >= 1; d = d / 2) {//将数组分割为多个子表
for (i = 0; i < d; i++) {//依次处理子表
for (j = i + d; j < n; j = j + d) {//按间隔处理子表
temp = A[j];
k = j - d;
while (k >= 0 && A[k] > temp) {
A[k + d] = A[k];
k = k - d;
}
A[k + d] = temp;
}
}
}
}
05快速排序
一句话描述:不断将数组最左边的数当做基准,在数组中找到这个基准的合适的位置,让基准左侧的数都小于这个基准,右侧的数都大于这个基准,然后用这个基准为界将数组两侧去递归调用
void kuaisu(int* pt, int start, int end,int n)
{
if (start >= end)
return;
int p1 = start;
int p2 = end;
int piv = pt[p1];
while(p1<p2)
{
while (p1 < p2 && pt[p2] >= piv)
{
p2--;
}
pt[p1] = pt[p2];
while (p1 < p2 && pt[p1] <= piv)
{
p1++;
}
pt[p2] = pt[p1];
}
pt[p1] = piv;
kuaisu(pt, start, p1 -1,n);
kuaisu(pt, p1 + 1, end,n);
}
01.将第一个数设为piv
02.p1为第一数,p2为最后一个数
02.从最右边开始找,直到找到小于piv的数,将p2移到这个位置,这个数放错了位置(小于piv的数应该在piv左边),于是将其放在p1的位置
03.从p1开始找大于piv的数,将p1移到这个位置,这个数放错了位置(大于piv的数应该在piv右边),于是将其放在p2的位置
04.p1p2经过0203步骤他们呈现贴近趋势,再重复0203,直到他们会和,会和的位置即piv做为分界数应该在的位置
05.以piv为界,两段的序列再分别重复12345步
06归并排序
一句话描述:归是递归,并是合并,通过dfs去分组,再回溯的过程中排序
void merge(int arr[], int l, int r) {
int n = r - l + 1;//临时数组存合并后的有序序列
int* tmp = new int[n];
int i = 0;
int left = l;
int q = (l + r) / 2;
int right = q + 1;
while (left <= q && right <= r)
tmp[i++] = arr[left] <= arr[right] ? arr[left++] : arr[right++];
while (left <= q)
tmp[i++] = arr[left++];
while (right <= r)
tmp[i++] = arr[right++];
for (int j = 0; j < n; ++j)
arr[l + j] = tmp[j];
delete[] tmp;//删掉堆区的内存
}
void mergesort(int arr[], int l, int r) {
if (l == r)
return; //递归基是让数组中的每个数单独成为长度为1的区间
int q = (l + r) / 2;
mergesort(arr, l, q);
mergesort(arr, q + 1, r);
merge(arr, l, r);
}