冒泡排序是我最开始学习C语言时候,第一个接触的排序算法,说实话,第一次写出来的时候,感觉是很神奇的,但是第二天又忘了,也是真的很痛苦。
//冒泡排序
void BubbleSort1(int* nums, int numsSize)
{
int i, j,count = 0;
for (i = 0; i < numsSize - 1; i++)
{
for (j = i + 1; j < numsSize; j++)
{
if (nums[i] > nums[j])
{
count++;
Swap(&nums[i], &nums[j]);
}
}
}
printf("BubbleSort1排序结束: count = %d 结果如下", count);
PrintNums(nums, numsSize);
}
上面是我在学习C语言中第一次学习冒泡排序时候别人教的,但是看上面那张图,
void BubbleSort2(int* nums, int numsSize)
{
int i, j, count = 0;
for (i = 0; i < numsSize - 1; i++)
{
for (j = numsSize - 1; j > i; j--)
{
if (nums[j - 1] > nums[j])
{
count++;
Swap(&nums[j-1], &nums[j]);
}
}
}
printf("BubbleSort2排序结束: count = %d 结果如下", count);
PrintNums(nums, numsSize);
}
冒泡排序的时间复杂度还是O(n^2)
选择排序,顾名思义就是靠选择来排序嘛。
//选择排序
void SelectionSort(int* nums, int numsSize)
{
int i,j,count = 0;
for (i = 0; i < numsSize - 1; i++)
{
int minIndex = 0;
for (j = i + 1; j < numsSize; j++)
{
//选择最小的出来
if (nums[j] < nums[minIndex])
{
minIndex = j;
}
}
if (i != minIndex)
{
//交换最小的
Swap(&nums[i], &nums[minIndex]);
count++;
}
}
printf("SelectionSort 排序结束: count = %d 结果如下", count);
PrintNums(nums, numsSize);
}
而它的交换次数相比于冒泡排序减少了很多次,优化了不少。
但是其时间复杂度还是O(n^2)
//插入排序
void InserctionSort(int* nums, int numsSize)
{
int i, j;
//i 从 1索引处开始,默认 0处已经排好了
for (i = 1; i < numsSize; i++)
{
//当前的数据,比前面小
if (nums[i] < nums[i - 1])
{
int tmp = nums[i];
//挪动数据
for (j = i - 1; nums[j] > tmp; j--)
{
nums[j + 1] = nums[j];
}
//找到合适的位置了
nums[j + 1] = tmp;
}
}
printf("InserctionSort 排序结束 结果如下");
PrintNums(nums, numsSize);
}
希尔排序我个人认为它就是插入排序的进阶版,而它是怎样去执行的,它是以一个区间一个区间去排序的。
下面是第一层循环的图片:当前的 区间增量是 4,然后区间增量会是一个这样的变化过程。
9/2 = 4(第一次) 4/2 = 2(第二次) 2/2 = 1(最后一次)
那么最后一次时候增量是1,它不就变成了上面刚刚说过的插入排序嘛?
所以前面的其实也是插入排序,不过就是有间隔的插入排序而已
看下图的比较,将incremen 变成1 不久和插入排序一样了吗?
下面是代码。
void ShellSort(int* nums, int numsSize)
{
int increment = numsSize;
while (increment > 1)
{
increment /= 2;
int i, j, tmp, end;
for (i = 0, j = i + increment; j < numsSize; i++, j++)
{
tmp = nums[j];
for (end = i; end >= 0 && nums[end] > tmp; end -= increment)
{
nums[end + increment] = nums[end];
}
nums[end + increment] = tmp;
}
}## 标题
printf("ShellSort 排序结束 结果如下");
PrintNums(nums, numsSize);
}
其时间复杂度是O(n^(3/2))d
归并排序的话充分的利用分治的思想,这个东西是递归,文字实在是不好太好表达。
代码如下:
void Merge(int* nums, int* tmpArr, int left, int mid, int right)
{
int i = left, j = mid+1, k = left; //i 代表mid左边的数组下标 j代表 mid 右边的数组下标, k则代表数组的开始位置,已经tmp数组的下标
//将有序序列纳入tmp数组
while (i < mid + 1 && j <= right)
{
if (nums[i] < nums[j])
{
tmpArr[k++] = nums[i++];
}
else
{
tmpArr[k++] = nums[j++];
}
}
//判断是否全部纳入
while (i < mid + 1)
{
tmpArr[k++] = nums[i++];
}
while (j <= right)
{
tmpArr[k++] = nums[j++];
}
//最后再拷贝回去
for (i = left; i < k; i++)
{
nums[i] = tmpArr[i];
}
}
void Msort(int* nums, int* tmpArr, int left, int right)
{
//数组中只有一个元素
if (left == right)
{
return;
}
int mid = (left + right) / 2;
Msort(nums, tmpArr, left, mid);
Msort(nums, tmpArr, mid + 1, right);
Merge(nums,tmpArr,left,mid,right);
}
void MergeSort(int* nums, int numsSize)
{
int* tmpArr = (int*)malloc(sizeof(int) & numsSize);
Msort(nums, tmpArr, 0, numsSize - 1);
printf("MergeSort 排序结束 结果如下");
PrintNums(nums, numsSize);
}
其时间复杂度是O(n * logn)
快速排序和前面的归并排序同样也是需要递归来实现的,在C语言中的qsort库函数就是快速排序。
void QSort(int* nums, int begin, int end)
{
if (begin >= end)
{
return;
}
int key = begin, left = begin, right = end;
while (left < right)
{
//找小的
while (left < right && nums[key] <= nums[right])
{
right--;
}
//找大的
while (left < right && nums[left] <= nums[key])
{
left++;
}
//交换两者
Swap(&nums[left], &nums[right]);
}
//于key进行交换
Swap(&nums[key], &nums[left]);
key = left;
//交换后,此时key左边的全部小于key右边的
QSort(nums, begin, key - 1);
QSort(nums, key+1, end);
}
void QuickSort(int* nums, int numsSize)
{
QSort(nums, 0, numsSize - 1);
printf("QuickSort 排序结束 结果如下");
PrintNums(nums, numsSize);
}
其时间复杂度是O(n * logn)