选择排序(Selection Sort)是一种简单直观的排序算法。它的工作原理是:首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
以下是一个使用C语言实现的选择排序算法:
#include
// 选择排序函数
void selectionSort(int arr[], int n)
{
int i, j, minIndex, temp;
// 遍历整个数组
for (i = 0; i < n-1; i++)
{
// 找到未排序部分的最小元素
minIndex = i;
for (j = i+1; j < n; j++)
{
if (arr[j] < arr[minIndex])
{
minIndex = j;
}
}
// 将找到的最小元素与第一个未排序的位置交换
if (minIndex != i)
{
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
// 打印数组
void printArray(int arr[], int size)
{
int i;
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
// 主函数
int main()
{
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr)/sizeof(arr[0]);
printf("原始数组: \n");
printArray(arr, n);
selectionSort(arr, n);
printf("排序后的数组: \n");
printArray(arr, n);
return 0;
}
selectionSort
函数:这是选择排序的主要实现部分。它接受一个整数数组 arr
和一个整数 n
(表示数组的大小)作为参数。
n-1
,因为最后一个元素在前面的迭代中已经被排序了。i+1
开始,在未排序的部分中查找最小元素。如果找到一个比当前最小元素还小的元素,我们更新 minIndex
。i
)交换。printArray
函数:这是一个辅助函数,用于打印数组的内容。
main
函数:这是程序的入口点。
arr
。n
中。selectionSort
函数对数组进行排序。这个选择排序的实现是升序排序,即从小到大。如果你想从大到小排序(降序),你只需要在内层循环中更改比较运算符即可(将 <
改为 >
)。
冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
以下是一个使用C语言实现的冒泡排序算法:
#include
// 冒泡排序函数
void bubbleSort(int arr[], int n)
{
int i, j, temp;
for (i = 0; i < n-1; i++)
{
// 标记位,用于优化,如果在某一趟排序中没有发生交换,说明序列已经有序,无需继续排序
int swapped = 0;
for (j = 0; j < n-i-1; j++)
{
// 如果当前元素大于下一个元素,则交换它们
if (arr[j] > arr[j+1])
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
// 标记发生了交换
swapped = 1;
}
}
// 如果在内层循环中没有交换过元素,说明数组已经是有序的
if (!swapped)
{
break;
}
}
}
// 打印数组
void printArray(int arr[], int size)
{
int i;
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
// 主函数
int main()
{
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原始数组:\n");
printArray(arr, n);
bubbleSort(arr, n);
printf("排序后的数组:\n");
printArray(arr, n);
return 0;
}
bubbleSort
函数:这是冒泡排序的主要实现部分。
n-1
趟(因为最后一个元素会在前面的迭代中自动到达正确的位置)。j
从 0
遍历到 n-i-1
,因为每趟排序后,最大的元素都会“冒泡”到序列的末尾,所以下一趟排序时就不必再考虑这些已经排好序的元素了。swapped
被设置为 1
,表示这一趟排序是有效的。如果在内层循环结束后 swapped
仍然是 0
,说明没有发生交换,数列已经有序,可以提前结束排序。printArray
函数:这是一个辅助函数,用于打印数组的内容。
main
函数:
arr
和它的大小 n
。bubbleSort
函数对数组进行排序。冒泡排序的时间复杂度在最坏和平均情况下是 O(n^2),其中 n 是要排序的元素数量。在最好情况下(即数组已经有序),如果使用了上述代码中的优化,时间复杂度可以降低到 O(n)。空间复杂度是 O(1),因为排序是在原地进行的,不需要额外的存储空间。
插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上通常使用in-place排序(即只需用到O(1)的额外空间)。
以下是一个使用C语言实现的插入排序算法:
#include
// 插入排序函数
void insertionSort(int arr[], int n)
{
int i, key, j;
for (i = 1; i < n; i++)
{
// 将arr[i]保存到key中,它是要被插入到前面已排序序列中的元素
key = arr[i];
// 从i-1开始向前扫描已排序序列,找到key应该插入的位置
j = i - 1;
// 如果扫描到的元素比key大,就将该元素移到下一个位置
while (j >= 0 && arr[j] > key)
{
arr[j + 1] = arr[j];
j = j - 1;
}
// 找到key的位置后,将key插入
arr[j + 1] = key;
}
}
// 打印数组
void printArray(int arr[], int size)
{
int i;
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
// 主函数
int main()
{
int arr[] = {12, 11, 13, 5, 6};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原始数组:\n");
printArray(arr, n);
insertionSort(arr, n);
printf("排序后的数组:\n");
printArray(arr, n);
return 0;
}
insertionSort
函数:
arr[i]
,我们将其值存储在key
中。i-1
开始,向前扫描已排序的部分,直到找到一个不大于key
的元素或到达数组的起始位置。key
大,就将该元素向右移动一位,为key
腾出插入的位置。key
的正确位置或到达数组起始位置时,退出内层循环,并将key
插入到该位置。printArray
函数:
main
函数:
arr
和数组的大小n
。insertionSort
函数对数组进行排序。插入排序的时间复杂度在最坏和平均情况下是O(n^2),其中n是要排序的元素数量。这是因为每次插入操作可能需要移动前面已排序序列中的所有元素。然而,对于部分已排序或小规模的数据集,插入排序可能会比其他O(n^2)算法(如冒泡排序)更快,因为它具有更少的交换操作。空间复杂度是O(1),因为排序是在原地进行的,不需要额外的存储空间。
选择排序、冒泡排序和插入排序都是基础的排序算法,它们各有特点。以下是它们之间的比较:
综上所述,选择排序、冒泡排序和插入排序在效率上相近,但在稳定性和简单性方面有所不同。在实际应用中,通常会选择更高效的排序算法,如快速排序、归并排序或堆排序。