1.插入排序
【1】基本实现:从一个数组的第二个位置起,到最后一个位置结束。让这些位置每一个都进行一遍循环。该循环操作是让从该位置上的元素起,依次与前面的位置元素进行比较,在满足某一条件下进行交换,从而达到排序的效果。
【2】时间复杂度:O(N^2)
//【排序1】插入排序--排升序--时间复杂度( O(N^2) )
void Insert_Sort(int* arr, int n)
{
for (int i = 1; i < n; i++)
{
for (int j = i; j > 0 && arr[j] < arr[j - 1]; j--)//对于已排部分,已经有序。因此只要有一次
//不满足交换条件,便可推出内部循环(该算法更优)
Swap(arr[j], arr[j - 1]);
}
}
注意 (j > 0) && ( arr[j] < arr[j - 1]) 这句代码
当我们从起始位置向前比较时,如果有一处不满足交换条件,那我们便没有必要在进行循环操作。因为前面部分我们已经对其进行过排序,这时判断加上(j > 0) && ( arr[j] < arr[j - 1])这样一句代码便可让其在完成排序任务的情况下提前退出内部循环,提高了效率。
- 冒泡排序
【1】时间复杂度:O(N^2)
```c
//【排序2】冒泡排序--排升序
void bubble_sort(int* arr, int n)
{
int flag = 1; //标记待排序数是否已经有序,1表示待排,0表示已有序
for (int i = 0; i < n && flag; i++)
{
flag = 0 ; //若经过一层循环还未交换,说明已经有序
for (int j = 0; j < n - i - 1 ; j++)
{
if (arr[j] > arr[j + 1])
{
Swap(arr[j], arr[j + 1]);
flag = 1 ;
}
}
}
}
3.归并排序
【1】:大致实现 :先将一块大的带排序的数据块分割成许多只有一个元素或两个元素的小的数据块,对其进行比较。最后将这些小的数据块拼接成大的数据块,从而达到排序效果。
【2】:时间复杂度:N*(Log N)
//【排序3】归并排序--排升序
void merge_sort(int* arr, int leftPos, int rightPos)
{
//【1】分割结束阶段--排序
if (rightPos - leftPos <= 1)
//分割成只剩下一个或两个元素,
{
if (rightPos - leftPos == 1 && arr[leftPos] > arr[rightPos])
Swap(arr[leftPos], arr[rightPos]);
return ;
}
//【2】递归分割
int mid = (rightPos + leftPos) >> 1 ;
merge_sort(arr , leftPos , mid);
merge_sort(arr , mid + 1, rightPos);
//【3】链接
int* temp = (int*)malloc(sizeof(int)* (rightPos - leftPos + 1));
int pos1 = leftPos, pos2 = mid + 1, k = 0;
//pos1,pos2链接的起始地点,k存放数据的地点
while (pos1 <= mid || pos2 <= rightPos)
{
//将左半部分拷贝到temp内:右半部分拷贝完,或左半部分小于右半部分的数
if (pos2 > rightPos || (pos1 <= mid && arr[pos1] < arr[pos2]))
//pos2>rightPos : 右半部分已经全放入temp中
temp[k++] = arr[pos1++];
else
temp[k++] = arr[pos2++];
}
memcpy(arr + leftPos, temp,(rightPos - leftPos + 1) * sizeof (int));
//将temp数组的数按序号排入arr数组内
free(temp);
}
该部分的解释已全部放入代码注释部分,该算法的代码理解有点难度。但还希望读者能够静心阅读注释部分。最后真心希望你能从中有所收获。
最后,因为笔者水平有限,如读者从中发现错误,欢迎指正。笔者不胜感激!