直接插入排序
使用场景:1.数据规模较小(n很小),则n^2也不会大。
2.待排序列越有序,则越快。
//直接插入排序,,每次向已经排好的队列中插入一个新值,再次保持有序,重复
//直到待排序的数全部取完
//具有稳定性,没有交换和跳着交换。时间复杂度O(n^2),空间复杂度O(1)
//希尔排序,相当于多次调用,直接插入排序
void InsertSort(int* arr, int len)
{
for (int i = 1; i < len; ++i)
{
//i在前
//将待排序的值存在temp
//从右往左比较,已经排好序的数,小于放左边,大于等于放右边
int temp = arr[i];
int j = i - 1;
for (; j >= 0; --j)
{
if (temp < arr[j])
{
//int temp = arr[i],
//如果使用arr[i] = arr[j], 如果待排序的值小于前面所有已经排好的数
// 就需要每向前一步,都需要给temp赋一次值,
// 其实导致待排序的只能和前一个数进行比较,
// 因为ar[i]一直没变
// arr[j] = temp;
arr[j+1] = arr[j];
//arr[j] = temp;遍历有序的,如果小每次都的赋值,浪费时间,只需要,最后放在temp大于的右边
}
else
{
break;
}
}
arr[j + 1] = temp;//遍历到0号位,如果将待排序的值放在右边。
}
}
希尔排序
gap[i] = {5,3,1}
使用场景:数据量大。(直接插入排序的优化版)
第一个排序算法:直接插入排序:每次从待排序队列中取一个值,放到已排序好的队列,再次保持有序,重复这样的动作,直到把待排序队列中的值全部取完 时间复杂度O(n^2) 空间复杂度O(1) 稳定的
第二个排序算法:希尔排序(缩小增量排序):是一个特殊的直接插入排序,相当于多次调用直接插入排序,每一次的增量保持互素,并且最后一个增量一定位1,为1才能保证其完全有序 时间复杂度O(n^1.3~1.5) 空间复杂度O(1) 不稳定
static void Shell(int* arr, int len, int gap)
{
for (int i = gap; i < len; i++)
{
//i在前
//将待排序的值存在temp
//从右往左比较,已经排好序的数,小于放左边,大于等于放右边
int temp = arr[i];
int j = i-gap; //gap就是划分的下一个节点
for (; j >= 0; j = j-gap)
{
if (temp < arr[j])
{
//int temp = arr[i],
//如果使用arr[i] = arr[j], 如果待排序的值小于前面所有已经排好的数
// 就需要每向前一步,都需要给temp赋一次值,
// 其实导致待排序的只能和前一个数进行比较,
// 因为ar[i]一直没变
// arr[j] = temp;
arr[j + gap] = arr[j];
//arr[j] = temp;遍历有序的,如果小每次都的赋值,浪费时间,只需要,最后放在temp大于的右边
}
else
{
break;
}
}
arr[j + gap] = temp;//遍历到0号位,如果将待排序的值放在右边。
}
}
void ShellSort(int* arr, int len)
{
int gap[] = { 5,3,1 };
int lengap = (sizeof(gap) / sizeof(gap[0]));
for (int i = 0; i < lengap; i++)
{
Shell(arr, len, gap[i]);
}
}
void print(int* arr,int len)
{
for (int i = 0; i < len; ++i)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int brr[] = { 2,10,5,34,17,28,11,9 };
int len = sizeof(brr) / sizeof(brr[0]);
InsertSort(brr, len);
print(brr, len);
ShellSort(brr, len);
print(brr, len);
}