稳定排序:排序前2个相等的数在序列中的前后位置顺序和排序后它们2个的前后位置顺序相同。(比如:冒泡、插入、基数、归并)
非稳定排序:排序前2个数的相对位置在排序后会发生改变。(比如:选择、快速、希尔、堆等)
插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。
插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。
在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。
void Insertion_Sort(int a[], int len)
{
//外层循环 - 插入数据量
for (int i = 1; i < len; i++)
{
//内层循环 - 每一趟需要做的事情
for (int j = i - 1; j > -1; j--)
{
if (a[j]>a[j + 1])
{
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
在下面函数中,通过使用一个临时变量temp来保存当前需要插入的元素。外层循环通过对整个待排序序列进行遍历,从第二个元素开始(下标为1),将当前元素保存在temp中。
然后,内层循环从当前元素的前一个元素开始向前遍历,直到找到合适的位置插入temp。在内层循环中,如果当前遍历到的元素大于temp,就将该元素后移一位,给temp腾出位置。
内层循环结束后,将temp插入到合适的位置,即将其赋值给a[j+1],这样就完成了一次元素的插入。
通过这种方式,不断地将元素逐个地插入到已排序的序列中,最终得到一个完全有序的序列。
void Insertion_Sort(int a[], int len)
{
int temp, i, j;
//外层循环 - 插入数据量
for (i = 1; i < len; i++)
{
temp = a[i];
//内层循环 - 每一趟需要做的事情
for (j = i - 1; j > -1 && a[j] > temp; j--)
{
a[j + 1] = a[j];
}
//移动结束
a[j + 1] = temp;
}
}
希尔排序(Shell Sort)是一种改进的插入排序算法,也被称为“缩小增量排序”(Diminishing Increment Sort)。希尔排序通过将待排序序列分割成多个子序列来进行排序,最终将这些子序列逐步合并为一个有序序列。
希尔排序的核心思想是通过定义一个增量序列(也称为间隔序列),将待排序序列划分成若干个子序列,并对这些子序列分别进行插入排序。随着排序的进行,增量序列会不断减小,直到变为1,此时对整个序列进行一次插入排序,最终完成排序。
希尔排序的步骤如下:
首先确定一个增量序列,一般选择初始增量为序列长度的一半,然后每次将增量折半,直到增量变为1。
对每个增量进行插入排序,即将待排序序列划分成若干个子序列,对每个子序列进行插入排序。
在每次插入排序中,按照增量的大小,将元素分组,对每组进行插入排序。
不断缩小增量,重复步骤2和步骤3,直到增量为1,进行最后一次插入排序,完成排序。
举个例子:
希尔排序函数:
//希尔排序
void Shell_Sort(int a[], int len)
{
int temp, i, j, n = 0;
//增量分组
int jump = len >> 1;
while (jump != 0)
{
//外层循环 - 插入数据量
for (i = jump; i < len; i++)
{
temp = a[i];
//内层循环
for (j = i - jump; j >= 0 && a[j]>temp; j -= jump)
{
a[j + jump] = a[j];
n += 1;
}
//移动结束
a[j + jump] = temp;
}
//增量更新
jump >>= 1;
}
}
分别在优化后的插入排序函数和希尔排序中定义一个变量n,用来统计各自进行数据交换的次数,结果如下:
插入排序交换的次数约是希尔排序交换次数的两倍!
快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序的核心思想是通过分治法将一个大的待排序序列逐步地分割成小的子序列,然后对这些子序列进行排序,最终得到一个有序序列。具体步骤如下:
以下是一个使用 C 语言实现的快速排序代码示例:
#include
// 交换两个元素的值
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 快速排序的递归函数
void quickSort(int arr[], int low, int high)
{
if (low < high)
{
int pivot = arr[low]; // 选择第一个元素作为基准元素
int i = low, j = high;
while (i < j)
{
while (i < j && arr[j] > pivot)
{
j--;
}
while (i < j && arr[i] <= pivot)
{
i++;
}
if (i < j)
{
swap(&arr[i], &arr[j]);
}
}
swap(&arr[low], &arr[i]);
quickSort(arr, low, i - 1); // 对左边子序列进行快速排序
quickSort(arr, i + 1, high); // 对右边子序列进行快速排序
}
}
// 打印数组元素
void printArray(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = {8, 5, 7, 3, 6, 1, 2, 8};
int size = sizeof(arr) / sizeof(arr[0]);
printf("原始数组:");
printArray(arr, size);
quickSort(arr, 0, size - 1);
printf("排序后数组:");
printArray(arr, size);
return 0;
}
输出结果:
分析程序:
代码首先定义了一个 swap
函数用于交换两个元素的值。然后,quickSort
函数使用递归实现了快速排序的具体操作。最后,在 main
函数中创建一个待排序的数组,并调用 quickSort
函数对数组进行排序。最终,通过调用 printArray
函数打印排序后的数组。