稳定性: 相同值的位置在排序后发生变化 那就说明此排序算法的稳定性差。
一 、直接插入排序
直接插入排序的时间复杂度是O(n^2)
空间复杂度是O(1)。
直接插入排序:每次从带排排序序列中取出一个值,放到已经排序好的序列中,然后依次保持有序
二、希尔排序
希尔排序:增效增量排序
原始数据:12 9 18 20 5 10 28 32 1 4 80 91 2 88 66
最小增量数组
(5, 3,1)注意最后一个增量必须为1。
从12向后数5**(增量为5)**,将10和12一个组。
第一组为12,10,80。
第二组为 9,28,91。
第三组为18,32,2。
第四组为20,1,88。
第五组为5,4,66。
每组依次排序,得到这个结果:
按增量3再进行排序:
最后按增量1进行排序:
此时排序完成。
直接插入越有序,排序越快,这也是希尔排序对插入排序优化的原因。
for循环的处理顺序:
希尔排序的时间空间复杂度:
时间复杂度为O(N^1.3~1.7)
空间复杂度是O(1)
因为存在跳跃交换所以稳定性较低。
三、归并排序
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ac10553c2ace3d5773e49fa495fcdb75.png)
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
void Merge_Sort(int* arr, int len, int gap)
{
int low1 = 0;
int hign1 = low1 + gap - 1;
int low2 = hign1 + 1;
int hign2 = low2+gap-1 <=len-1 ? low2 + gap - 1 : len - 1;
int k = 0;
int* brr = (int*)malloc(sizeof(int) * 30);
while (low2 < len)
{
while (low1 <= hign1 && low2 <= hign2)
{
if (arr[low1] > arr[low2])
{
brr[k++] = arr[low2++];
}
if (arr[low1] <= arr[low2])
{
brr[k++] = arr[low1++];
}
}
//for(int i=0;i<gap;++i)
while (low1 <= hign1)
{
brr[k++] = arr[low1++];
}
while (low2 <= hign2)
{
brr[k++] = arr[low2++];
}
low1 = hign2 + 1;
hign1 = low1 + gap - 1;
low2 = hign1 + 1;//用low2确定右侧是否有数据的状态
hign2 = low2 + gap - 1 < len ? low2 + gap - 1 : len - 1;
}
while (low1<len)
{
brr[k++] = arr[low1++];
}
for (int i = 0; i < len; ++i)
{
arr[i] = brr[i];
}
free(brr);
}
void Show(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%4d", arr[i]);
}
}
void Merge(int* arr, int len)
{
int gap = 0;
for (int i = 1; i < len; i *= 2)
{
gap = i;
Merge_Sort(arr,len,gap);
}
}
int main()
{
int arr[] = { 8423,34,45,56,67,78,879,345,45,12,90,84,8,12 };
int len = sizeof(arr) / sizeof(arr[0]);
Merge(arr, len);
Show(arr, len);
return 0;
}
归并排序的时间空间复杂度:
时间复杂度为:O(nlogn)
空间复杂度为:O(n)
归并排序不存在跳跃交换,遂稳定。
四、快排
因为存在跳跃交换,所以属于不稳定的排序。
时间复杂度为平均nlogn,空间复杂度为logn,理由是如下函数 在递归实现时,函数没结束时,
一直在申请栈空间(变量par).
`void Quick(int* arr,int left,int right)
{
int par=Quick_Sort(arr, left, right);
if (par > left + 1)
{
Quick(arr, left, par - 1);
}
if (par <right-1)
{
Quick(arr, par + 1,right);
}
}`
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
int Quick_Sort(int* arr, int left, int right)
{
int tmp = arr[left];
while(left<right)//确保至少有两个值 才进入排序循环*********
{
while (left<right && arr[right]>tmp)
{
right--;
}
if (right == left)
{
arr[right] = tmp;
return right;
}
arr[left] = arr[right];
while (left < right && arr[left] <=tmp)// <=tmp 没加等号
{
left++;
}
if (left == right)
{
arr[left] = tmp;//这两行代码换成BREAK也可以。
return left;
}
arr[right] = arr[left];
}
arr[left] = tmp;//因为大循环的意思没领悟 所以这儿就没想清楚
return left;
}
void Quick(int* arr,int left,int right)
{
int par=Quick_Sort(arr, left, right);
if (par > left + 1)
{
Quick(arr, left, par - 1);
}
if (par <right-1)
{
Quick(arr, par + 1,right);
}
}
void Show(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 12,34,45,56,23,34,56,2,234,45,23,34,45,67,23 };
int len = sizeof(arr) / sizeof(arr[0]);
Quick(arr,0,len-1);
Show(arr, len);
return 0;
}
不用递归的代码实现
void Quick_Stack(int* arr, int left, int right)
{
std::stack<int> st;
int par = Quick_Sort(arr, left, right);
if (par > left + 1)
{
//=Quick_Sort(arr, left, par - 1);
st.push(par - 1);
st.push(left);
}
if (par < right - 1)
{
//Quick_Sort(arr, par + 1, right);
st.push(right);
st.push(par + 1);
}
while (!st.empty())
{
left=st.top();
st.pop();
right = st.top();
st.pop();
par=Quick_Sort(arr,left,right);
if (par > left + 1)
{
//=Quick_Sort(arr, left, par - 1);
st.push(par - 1);
st.push(left);
}
if (par < right - 1)
{
//Quick_Sort(arr, par + 1, right);
st.push(right);
st.push(par + 1);
}
}
}
五、选择排序
void Select_Sort(int* arr, int len)
{
int left = 0;
int min = 0;
int tmp = 0;
while (left < len - 1)
{
min = left;
for (int i = left; i < len; i++)
{
if (arr[i] < arr[min])
{
//tmp = min;
min = i;
}
}
tmp = arr[left];
arr[left] = arr[min];
arr[min] = tmp;
left++;
}
}
void Show(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 12,2,34,4,32,44,3,23,34,89 };
int len = sizeof(arr) / sizeof(arr[0]);
Select_Sort(arr, len);
Show(arr, len);
return 0;
}
选择排序的时间空间复杂度:
时间复杂度:O(n^2)
空间复杂度:O(1)
不稳定
六、基数排序
时间复杂度为O(dn)
空间复杂度为O(dn)
稳定性:稳定
int Count = 0;
void Show(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int Get_bit(int* arr, int len)
{
int i = 0;
int max = 0;
while (i < len)
{
if (arr[i] > max)
{
max = arr[i];
}
i++;
}
while (max / 10 != 0)
{
max /= 10;
Count++;
}
Count++;
//for (int j = 0; j < Count; ++j)
//{
// Classify(arr, len);
//}
return Count;
}
int Gey_remainder(int n, int fin)
{
for (int i = 0; i < fin; ++i)
{
n /= 10;
}
return n % 10;
}
void Classify(int* arr, int len,int fin)
{
std::queue<int> bucket[10];
for (int i = 0; i < len; i++)
{
int index = Get_remainder(arr[i], fin);
bucket[index].push(arr[i]);
}
int k = 0;
for (int i = 0; i <= 9; i++)
{
while (!bucket[i].empty()) //不能取一个就拉倒了,都得取走。
{
arr[k++] = bucket[i].front(); //1.一个筒子值都取完再取下一个筒子。
bucket[i].pop();
}
}
}
void redix_sort(int* arr, int len)
{
int fin=Get_bit(arr, len);
for (int i = 0; i < fin; ++i)
{
Classify(arr, len,i); //i控制个位十位百位取余,控制趟数。
}
}
int main()
{
int arr[] = { 12,2,34657,23456,23,5,80,232,56,89,3,23,34,89 };
int len = sizeof(arr) / sizeof(arr[0]);
redix_sort(arr, len);
Show(arr, len);
return 0;
}