本文介绍了几种常见的排序算法的实现,包括冒泡排序、选择排序、插入排序、希尔排序、归并排序和快速排序。冒泡排序通过多次遍历数组,比较并交换相邻元素,逐步将较小元素“浮”到数组顶端,时间复杂度为O(n^2)
。选择排序通过选择未排序部分的最小元素进行交换,逐步完成整个数组排序,同样具有O(n^2)
的时间复杂度。插入排序将数组分为已排序和未排序部分,逐个插入未排序元素到已排序部分的合适位置,时间复杂度为O(n^2)
。希尔排序是插入排序的改进版本,通过分组插入排序,最终得到有序数组,时间复杂度在O(n log n)
到O(n^2)
之间。归并排序采用分治策略,递归拆分和合并数组,时间复杂度始终为O(n log n)
,但需要额外空间。最后,快速排序通过选择基准值划分数组,并递归排序子数组,平均时间复杂度为O(n log n)
,但最坏情况下为O(n^2)
。这些算法各有特点,适用于不同场景。
冒泡排序(Bubble Sort)算法,冒泡排序是一种简单的排序算法,它多次遍历待排序的元素,依次比较相邻的两个元素,若顺序不对则交换它们,直到整个序列有序。算法的名字源于越小的元素会经过交换“浮”到数组的顶端。
这里的BubbleSort
函数接受一个整数数组 Array
和数组的大小 ArraySize
作为参数,然后对该数组进行升序排序。排序过程采用嵌套的两个循环,外层循环(x 循环)控制每一轮的遍历,内层循环(y 循环)用于比较相邻元素并进行交换。
具体实现步骤:
这种排序算法的时间复杂度为 O(n^2)
,其中 n 是数组的大小。虽然冒泡排序不是最有效的排序算法,但它简单易懂,适用于小型数据集或部分有序的数据。在实际应用中,对于大型数据集,通常会选择更高效的排序算法,如快速排序或归并排序。
#include
void BubbleSort(int Array[], int ArraySize)
{
int x, y, temporary;
for (x = 0; x < ArraySize - 1; x++)
{
for (y = ArraySize - 1; y > x; y--)
{
if (Array[y-1] > Array[y])
{
temporary = Array[y-1];
Array[y-1] = Array[y];
Array[y] = temporary;
}
}
}
}
int main(int argc, char* argv[])
{
int a[10] = { 2, 5, 6, 8, 2, 3, 9, 1, 8, 0 };
BubbleSort(a, 10);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
system("pause");
return 0;
}
选择排序(Selection Sort)算法,选择排序是一种简单直观的排序算法。它的基本思想是通过不断选择数组中未排序部分的最小元素,并将其与未排序部分的第一个元素交换位置,从而逐步完成整个数组的排序。
具体步骤如下:
选择排序的主要特点是不涉及大量的数据移动,但由于其时间复杂度为O(n^2)
,在大规模数据集上性能较差。
#include
void SelectSort(int Array[], int ArraySize)
{
int x, y, minimum, temporary;
for (x = 0; x < ArraySize - 1; x++)
{
minimum = x; // 假设x是最小的数
for (y = x + 1; y < ArraySize; y++)
{ // 将假设中的最小值进行比对
if (Array[y] < Array[minimum])
minimum = y;
}
if (minimum != x)
{ // 循环结束后进行交换
temporary = Array[minimum];
Array[minimum] = Array[x];
Array[x] = temporary;
}
}
}
int main(int argc, char* argv[])
{
int a[10] = { 2, 5, 6, 8, 2, 3, 9, 1, 8, 0 };
SelectSort(a, 10);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
system("pause");
return 0;
}
插入排序(Insertion Sort)算法,插入排序是一种简单直观的排序算法,其基本思想是将数组分为已排序和未排序两部分,逐个将未排序部分的元素插入到已排序部分的合适位置。
具体步骤如下:
插入排序是一种稳定的排序算法,对于小型数据集或已经基本有序的数据集,性能较好。插入排序的平均时间复杂度为O(n^2)
,适用于小规模数据排序。
#include
void InsertSort(int Array[], int ArraySize)
{
int x, y, temporary;
for (x = 1; x < ArraySize; x++)
{
if (Array[x] < Array[x - 1])
{
temporary = Array[x]; // 把小的元素放入temp
for (y = x - 1; Array[y] > temporary; y--)
{
Array[y + 1] = Array[y];
}
Array[y + 1] = temporary;
}
}
}
int main(int argc, char* argv[])
{
int a[10] = { 2, 5, 6, 8, 2, 3, 9, 1, 8, 0 };
InsertSort(a, 10);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
system("pause");
return 0;
}
希尔排序(Shell Sort)算法,希尔排序是一种改进的插入排序算法,其基本思想是通过将数组分成若干个子序列进行插入排序,逐渐缩小子序列的间隔,最终使整个数组成为一个有序序列。
具体步骤如下:
希尔排序的时间复杂度受到间隔序列的选择影响,通常平均时间复杂度在O(n log n)
到O(n^2)
之间。希尔排序相对于插入排序来说,在处理中等规模数据时性能较好。
#include
void ShellSort(int Array[], int ArraySize)
{
int x, y, temporary;
int interval = ArraySize; // 设置排序间隔
do
{
interval = interval / 3 + 1;
for (x = interval; x < ArraySize; x++)
{
if (Array[x] < Array[x - interval])
{
temporary = Array[x]; // 把小的元素放入temp
for (y = x - interval; Array[y] > temporary; y -= interval)
{
Array[y + interval] = Array[y];
}
Array[y + interval] = temporary;
}
}
} while (interval > 1);
}
int main(int argc, char* argv[])
{
int a[10] = { 2, 5, 6, 8, 2, 3, 9, 1, 8, 0 };
ShellSort(a, 10);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
system("pause");
return 0;
}
归并排序(Merge Sort)算法,归并排序是一种分治算法,其基本思想是将数组分成两个部分,对每个部分进行递归排序,然后将两个有序的子数组合并成一个有序数组。
具体步骤如下:
归并排序的时间复杂度始终为O(n log n)
,并且具有稳定性,但相对于其他排序算法,归并排序需要额外的空间来存储临时数组。
#include
#define MAXSIZE 10
// 实现归并,并把最后的结果存放到list1里面
void merging(int *list1,int list1_size,int *list2,int list2_size)
{
int list1_sub = 0, list2_sub = 0, k = 0;
int temporary[MAXSIZE];
while (list1_sub < list1_size && list2_sub < list2_size)
{
if (list1[list1_sub] < list2[list2_sub])
temporary[k++] = list1[list1_sub++];
else
temporary[k++] = list2[list2_sub++];
}
while (list1_sub < list1_size)
temporary[k++] = list1[list1_sub++];
while (list2_sub < list2_size)
temporary[k++] = list2[list2_sub++];
// 最后将归并后的结果存入到list1变量中
for (int m = 0; m < (list1_size + list2_size); m++)
list1[m] = temporary[m];
}
// 拆分数组,拆分以后传入merging函数实现归并
void MergeSort(int Array[], int ArraySize)
{ // 如果大于1则终止拆解数组
if (ArraySize > 1)
{
int *list1 = Array; // 左边部分
int list1_size = ArraySize / 2; // 左边的尺寸,每次是n/2一半
int *list2 = Array + ArraySize / 2; // 右半部分,就是左半部分的地址加上右半部分的尺寸
int list2_size = ArraySize - list1_size; // 右半部分尺寸
MergeSort(list1, list1_size); // 递归拆解数组1
MergeSort(list2, list2_size); // 递归拆解数组2
merging(list1, list1_size, list2, list2_size); // 归并
}
}
int main(int argc, char* argv[])
{
int a[10] = { 2, 5, 6, 8, 2, 3, 9, 1, 8, 0 };
MergeSort(a, 10);
for (int i = 0; i < 10; i++)
printf("%d ", a[i]);
system("pause");
return 0;
}
快速排序(Quick Sort)算法,快速排序是一种分治算法,其基本思想是选择数组中的一个元素作为基准值,然后将数组划分为两个子数组,一个子数组中的元素都小于基准值,另一个子数组中的元素都大于基准值。对这两个子数组进行递归排序,最终得到有序数组。
具体步骤如下:
快速排序是一种高效的排序算法,平均时间复杂度为O(n log n)
,但最坏情况下可能达到O(n^2)
。在实际应用中,通常表现优秀。
#include
void QuckSort(int s[], int start, int end)
{
int i, j;
i = start;
j = end;
s[0] = s[start]; //设置基准值
while (i<j)
{
while (i<j&&s[0]<s[j])
j--; // 位置左移
if (i<j)
{
s[i] = s[j]; // 将s[j]放到s[i]的位置上
i++; // 位置右移
}
while (i<j&&s[i] <= s[0])
i++; // 位置右移
if (i<j)
{
s[j] = s[i]; // 将大于基准值的s[j]放到s[i]位置
j--; // 位置右移
}
}
s[i] = s[0]; // 将基准值放入指定位置
if (start<i)
QuckSort(s, start, j - 1); // 对分隔出的部分递归调用函数qusort()
if (i<end)
QuckSort(s, j + 1, end);
}
int main(int argc, char *argv[])
{
int Array[11] = { 4, 6, 7, 8, 2, 1, 4, 5, 5, 0 };
QuckSort(Array, 0, 10);
for (int x = 0; x < 10; x++)
{
printf("%d ", Array[x]);
}
getchar();
return 0;
}