关于各大排序的简单介绍
算法稳定性:
算法稳定性 -- 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!
插入排序:
直接插入排序:
概念:
将一条记录插入到已经排好序的序表中,得到一个新的有序表。(时间复杂度是O(n^2),空间复杂度为O(1))
对应相应的顺序查找。
例子:
#include <stdio.h>
#include <stdlib.h>
void InsertSort(int *a, int length)
{
int i , j;
for(i = 1;i <= length; i++)
{
if(a[i] < a[i - 1])
{
int temp = a[i];
for(j = i - 1; j >= 0 && a[j] > temp; j--)
{
a[j + 1] = a[j];
}
a[j+1] = temp;
}
}
for(i = 0; i <= length; i++)
printf("%d ", a[i]);
}
int main(void)
{
int i;
int a[] = {49, 38, 65, 97, 76, 13, 27, 49};
int k = sizeof(a) / sizeof(a[0]);
InsertSort(a, k - 1);
return 0;
}
折半插入排序:
对应折半查找或二分查找
概念:对插入排序的改进。
百度百科:https://baike.baidu.com/item/折半插入排序/8208853
在将一个新元素插入已排好序的数组的过程中,寻找插入点时,将待插入区域的首元素设置为a[low],末元素设置为a[high],则轮比较时将待插入元素与a[m],其中m=(low+high)/2相比较,如果比参考元素小,则选择a[low]到a[m-1]为新的插入区域(即high=m-1),否则选择a[m+1]到a[high]为新的插入区域(即low=m+1),如此直至low<=high不成立,即将此位置之后所有元素后移一位,并将新元素插入a[high+1]。(时间复杂度和空间复杂度和插入排序相同)
代码:
https://www.cnblogs.com/tensory/p/6590799.html
void InsertSort2(int *a, int length)
{
int i , j, low, high, mid;
for(i = 1; i < length; i++)
{
low = 0;
high = i - 1;
while(low <= high)
{
mid = (low + high) / 2;
if(a[mid] < a[i])
{
low = mid + 1;
}else
{
high = mid - 1;
}
}
int temp = a[i];
for(j = i; j > low; j--)
a[j] = a[j - 1];
a[low] = temp;
}
for(i = 0; i <= length; i++)
printf("%d ", a[i]);
}
希尔排序:
概念:
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
代码:
下面是我认为写的比较好的两个博客:
https://www.cnblogs.com/chengxiao/p/6104371.html
https://www.cnblogs.com/skywang12345/p/3597597.html
void shell_sort(int *a, int length)
{
int i, j, gap; //gap是步长每次减少为原来的一半
for(gap = length / 2; gap > 0; gap /= 2) //每次重新设置步长
{
for(i = 0; i < gap; i++) //有gap个组,对每个组执行插入排序
{
//开始排序
for(j = i + gap; j < length; j += gap) //对于偶数就是两两一组,奇数第一组是3个比较
{
if(a[j] < a[j - gap])
{
int tmp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > tmp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = tmp;
}
}
}
}
for(i = 0; i <= length; i++)
printf("%d ", a[i]);
}
交换排序:
冒泡排序:(最简单的交换排序)
概念:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
代码:
void bubble_sort04(int *a, int length)
{//外层循环控制趟数,总趟数为len-1
int i, j;
for(i = 0; i < length - 1; i++)
{
for (j = 0; j < length - 1 - i; j++) //内层循环为当前i趟数 所需要比较的次数
{
if (a[j] > a[j + 1])
{
int temp;
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
for(i = 0; i <= length; i++)
printf("%d ", a[i]);
}
快速排序:
概念:
https://baike.baidu.com/item/快速排序算法?fromtitle=快速排序&fromid=2084344
它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
代码:
https://www.jianshu.com/p/5f38dd54b11f
void quick_sort01(int *a, int left, int right)
{
if(left < right)
{
left = quick_sort02(a, 0, right);
quick_sort02(a, 0, left - 1);
quick_sort02(a, left + 1, right);
}
}
int quick_sort02(int *a, int left, int right)
{
if(left < right)
{
int temp = a[left];
while(left < right)
{
while(left < right && a[right] >= temp)
right--;
a[left] = a[right];
while(left < right && a[left] <= temp)
left++;
a[right] = a[left];
a[left] = temp;
}
}
return left;
}
选择排序:
简单选择排序:
概念:
我理解的是每次从未排序中选择最小的数放在已排序的后面
代码:
https://blog.csdn.net/lemonchi/article/details/81364424
void selectSort(int *a, int length)
{
int i, j, min, temp;
for(i = 0; i < length; i++)
{
min = i;
for(j = i + 1; j <= length; j++)
{
if(a[j] < a[min])
min = j;
}
temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
树形选择排序:
概念:
代码
堆排序:
归并排序:
基数排序:
多关键字排序:
链式基数排序:
外部排序:
多路平衡归并排序:
置换-选择排序:
最佳归并数:
概念:
实例:
冒泡排序:
概念:
实例:
快速排序:
概念:
实例:
插入排序:
概念:
实例: