目录
[二、常见排序算法的运行方式和 C 语言实现](#二、常见排序算法的运行方式和 C 语言实现)
[1. 冒泡排序](#1. 冒泡排序)
[2. 选择排序](#2. 选择排序)
[3. 插入排序](#3. 插入排序)
[4. 归并排序](#4. 归并排序)
[5. 快速排序](#5. 快速排序)
[1. 时间复杂度](#1. 时间复杂度)
[2. 空间复杂度](#2. 空间复杂度)
[3. 稳定性](#3. 稳定性)
一、排序算法的基本概念
排序算法是指将一组无序的数据元素按照特定的顺序进行排列的过程。常见的排序算法有:
-
冒泡排序 (Bubble Sort):通过比较相邻元素,将较大的元素交换到后面,逐次遍历整个数组,直到数组有序。
-
选择排序 (Selection Sort):在未排序的数组中找到最小元素,将其与第一个元素交换位置,然后在剩余未排序的数组中继续寻找最小元素,并与第二个元素交换位置,以此类推。
-
插入排序 (Insertion Sort):将数组分为已排序和未排序两个部分,每次从未排序部分中取出第一个元素,将其插入到已排序部分的合适位置,直到所有元素都排序完毕。
-
归并排序 (Merge Sort):将数组递归地分成两半,直到每个子数组只有一个元素,然后将两个有序子数组合并成一个有序数组。
-
快速排序 (Quick Sort):选择一个基准元素,将数组中比基准元素小的元素放在基准元素的左边,比基准元素大的元素放在基准元素的右边,然后递归地对左右两部分进行排序。
二、常见排序算法的运行方式和 C 语言实现
1. 冒泡排序
-
运行方式:
-
比较相邻元素,如果顺序错误则交换。
-
遍历数组,重复比较和交换,直到没有元素需要交换。
-
-
C 语言实现:
cppvoid bubbleSort(int arr[], int n) { int i, j, temp; for (i = 0; i < n - 1; i++) { 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; } } } }
流程图:
2. 选择排序
-
运行方式:
-
找到未排序数组中的最小元素。
-
将最小元素与第一个元素交换位置。
-
重复上述步骤,直到所有元素都排序完毕。
-
-
C 语言实现:
cppvoid 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; } } temp = arr[minIndex]; arr[minIndex] = arr[i]; arr[i] = temp; } }
流程图:
3. 插入排序
-
运行方式:
-
将第一个元素视为已排序数组。
-
从第二个元素开始,每次将一个元素插入到已排序数组中的合适位置。
-
-
C 语言实现:
cppvoid insertionSort(int arr[], int n) { int i, j, key; for (i = 1; i < n; i++) { key = arr[i]; j = i - 1; while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } }
流程图:
4. 归并排序
-
运行方式:
-
将数组递归地分成两半,直到每个子数组只有一个元素。
-
将两个有序子数组合并成一个有序数组。
-
-
C 语言实现:
cppvoid merge(int arr[], int left, int mid, int right) { int n1 = mid - left + 1; int n2 = right - mid; int L[n1], R[n2]; int i, j, k; for (i = 0; i < n1; i++) { L[i] = arr[left + i]; } for (j = 0; j < n2; j++) { R[j] = arr[mid + 1 + j]; } i = 0; j = 0; k = left; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } void mergeSort(int arr[], int left, int right) { if (left < right) { int mid = left + (right - left) / 2; mergeSort(arr, left, mid); mergeSort(arr, mid + 1, right); merge(arr, left, mid, right); } }
流程图:
5. 快速排序
-
运行方式:
-
选择一个基准元素。
-
将数组中比基准元素小的元素放在基准元素的左边,比基准元素大的元素放在基准元素的右边。
-
递归地对左右两部分进行排序。
-
-
C 语言实现:
cppint partition(int arr[], int low, int high) { int pivot = arr[high]; int i = (low - 1); for (int j = low; j <= high - 1; j++) { if (arr[j] < pivot) { i++; swap(arr, i, j); } } swap(arr, i + 1, high); return (i + 1); } void quickSort(int arr[], int low, int high) { if (low < high) { int pi = partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } } void swap(int arr[], int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }
流程图:
三、排序算法的深度分析
1. 时间复杂度
-
冒泡排序、选择排序和插入排序的时间复杂度都是 O(n^2),这意味着它们的运行时间随着数据量的增加呈平方增长。
-
归并排序和快速排序的时间复杂度都是 O(n log n),这意味着它们的运行时间随着数据量的增加呈线性增长。
2. 空间复杂度
-
冒泡排序、选择排序和插入排序的空间复杂度都是 O(1),这意味着它们不需要额外的空间。
-
归并排序的空间复杂度是 O(n),因为它需要额外的空间来存储合并后的数组。
-
快速排序的空间复杂度是 O(log n),因为它需要递归调用。
3. 稳定性
-
稳定排序算法是指在排序过程中,如果两个元素的值相等,它们的相对顺序不会改变。
-
冒泡排序、插入排序和归并排序是稳定的排序算法。
-
选择排序和快速排序是不稳定的排序算法。
四、总结
不同的排序算法有不同的时间复杂度、空间复杂度和稳定性,适合不同的应用场景。对于小规模的数据集,冒泡排序、选择排序和插入排序就足够了。对于大规模的数据集,归并排序和快速排序是更好的选择。
五、其他
除了上面提到的排序算法,还有很多其他的排序算法,例如:
-
堆排序 (Heap Sort)
-
基数排序 (Radix Sort)
-
桶排序 (Bucket Sort)
选择合适的排序算法取决于具体的应用场景,需要根据数据量、数据分布、时间复杂度、空间复杂度和稳定性等因素进行权衡。