Note:本来打算把排序都写在一块儿,所以生成的随机数组本意是要重复用的,因此在排序算法里又赋值了一个数组。但发现写一块儿可能太乱了,就把不同的排序分开写了,函数里的数组就不带的删了,不影响。
直接插入排序
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void PutNum(int *p, int n);//输出数组
void CreatRandomNum(int *p, int n);//生成随机数序列
void InsertSort(int a[], int n);//插入排序
int main() {
int a[10] = {0};
int length = sizeof(a) / sizeof(a[0]);
CreatRandomNum(a, length);
printf("待排序序列为:");
PutNum(a, length);
InsertSort(a, length);//插入排序
return 0;
}
void InsertSort(int a[], int n) {
int b[10] = {0};
for (int i = 0; i < n; i++)
b[i] = a[i];
for (int i = 1; i < n; i++) {
if (b[i] < b[i - 1]) {//当两个数相同不会发生移动,所以算法稳定。
int j = i - 1;//从i的前一位开始比较
int index = b[i];
for (; index < b[j] && j >= 0; j--)//找插入位置,顺便向后挪位
b[j + 1] = b[j];
b[j + 1] = index;//若位置i上的数a满足条件,则下一轮i指向i-1,但i-1上的数b不满足条件,
} //则数字应该插在数字a的位置上。
}
printf("\n排序后序列为:");
PutNum(b, n);
}
void CreatRandomNum(int *p, int n) {
srand(time(0));
while (n-- > 0) {
*p++ = rand() % 100 + 1;
}
}
void PutNum(int *p, int n) {
while (n-- > 0)
printf("%d ", *p++);
}
折半插入排序
与直接插入排序相比,优化了查找插入位置的速度,但还是要往后移动,所以整体上时间复杂度没有太大提升。适用于数据量不大的排序。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void PutNum(int *p, int n);//输出数组
void CreatRandomNum(int *p, int n);//生成随机数数组
void InsertSort(int a[], int n);
int main() {
int a[10] = {0};
int length = sizeof(a) / sizeof(a[0]);
CreatRandomNum(a, length);
printf("待排序数组为:");
PutNum(a, length);
InsertSort(a, length);
}
/* 若当前待插入数字为a,在查找待插入位置时,最后一轮停在low = high = mid,mid之前的数都小于a
之后的数都大于a。
若a > [mid位置上的数],则low = mid +1,--->low > high,循环终止,则a应放在 [high+1]的位置上
若a < [mid位置上的数], 则 high = mid -1,---> low > high,循环终止,则a应放在[high+1]的位置上
若a = [mid位置上的数], low = mid +1,同上
所以:a最终应该放在high+1的位置上,易得相同的数之间的次序不会变,所以算法是稳定的。
*/
void InsertSort(int arr[], int length) {
int low, high, mid, tmp;
for(int i=1; i<length; i++) {
if(arr[i] < arr[i-1]) {
tmp = arr[i];
low = 0;
high = i-1;
while(low <= high) {
mid = (low + high)/2;
if(tmp < arr[mid])
high = mid - 1;
else
low = mid + 1;
}
for(int j=i-1; j>=low; j--)
arr[j+1] = arr[j];
arr[low] = tmp;
}
}
printf("\n排序后数组为:");
PutNum(arr, length);
}
void CreatRandomNum(int *p, int n) {
srand(time(0));
while (n-- > 0)
*p++ = rand() % 100 + 1;
}
void PutNum(int *p, int n) {
while (n-- > 0)
printf("%d ", *p++);
}
希尔排序
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void PutNum(int *p, int n);//输出数组
void CreatRandomNum(int *p, int n);//生成随机数数组
void ShellSort(int a[], int n);//希尔排序
int main() {
int a[10] = {0};
int length = sizeof(a) / sizeof(a[0]);
CreatRandomNum(a, length);
printf("待排序数组为:");
PutNum(a, length);
ShellSort(a, length);
}
/*
就是在直接插入排序上加了一个“分组”;
在长度为d的分组内进行直接插入排序。
当两个具有相同值的数字分在两个不同组时,两个数的相对前后次序就可能变化,
所以希尔排序不稳定。
*/
void ShellSort(int a[], int n) {
int b[10] = {0};
for (int i = 0; i < n; i++)
b[i] = a[i];
for (int d = n / 2; d >= 1; d /= 2 ) { //d为步长
for (int i = d; i < n; i += d) {
if (b[i] < b[i - d]) {
int j = i - d;
int index = b[i];
for (; j >= 0 && index < b[j]; j -= d)
b[j + d] = b[j];
b[j + d] = index;
}
}
}
printf("\n排序后数组为:");
PutNum(b, n);
}
void PutNum(int *p, int n) {
while (n-- > 0)
printf("%d ", *p++);
}
void CreatRandomNum(int *p, int n) {
srand(time(0));
while (n-- > 0)
*p++ = rand() % 100 + 1;
}