📚 排序算法概述
什么是排序?
排序(Sorting)是将一组数据按照特定顺序(升序或降序)重新排列的过程。排序是计算机科学中最基本的算法之一。
- ✅ 升序排序:从小到大(1, 2, 3, 4, 5)
- ✅ 降序排序:从大到小(5, 4, 3, 2, 1)
- ✅ 应用场景:成绩排名、商品排序、数据检索
- 💡 学习价值:理解算法思想,为高级算法打基础
💡 为什么要学习多种排序算法?
• 不同算法有不同的性能特点
• 适合不同的数据规模和场景
• 理解算法设计思想和优化技巧
冒泡排序(Bubble Sort)
核心思想:重复遍历数组,比较相邻元素,如果顺序错误就交换它们。每一轮遍历会将最大的元素"冒泡"到末尾。
选择排序(Selection Sort)
核心思想:每一轮从未排序部分找到最小(或最大)元素,放到已排序部分的末尾。
⚙️ 算法实现
冒泡排序完整实现
#include <iostream>
using namespace std;
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "排序前:";
printArray(arr, n);
bubbleSort(arr, n);
cout << "排序后:";
printArray(arr, n);
return 0;
}
选择排序完整实现
#include <iostream>
using namespace std;
void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (minIndex != i) {
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "排序前:";
printArray(arr, n);
selectionSort(arr, n);
cout << "排序后:";
printArray(arr, n);
return 0;
}
🎮 互动实验:排序演示
输入数组元素,查看两种排序的过程
输入数组后点击按钮...
🛠️ 算法比较
两种排序的对比
| 特性 |
冒泡排序 |
选择排序 |
| 最好时间复杂度 |
O(n)(优化后) |
O(n²) |
| 平均时间复杂度 |
O(n²) |
O(n²) |
| 最坏时间复杂度 |
O(n²) |
O(n²) |
| 空间复杂度 |
O(1) |
O(1) |
| 稳定性 |
稳定 |
不稳定 |
| 交换次数 |
较多 |
较少(最多n-1次) |
💡 关键区别:
• 冒泡排序:通过不断交换相邻元素来排序,可以提前终止
• 选择排序:每轮只交换一次,交换次数少,但无法提前终止
• 两者都是O(n²),适合小规模数据
冒泡排序的优化
void optimizedBubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
bool swapped = false;
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
if (!swapped) {
break;
}
}
}
void betterBubbleSort(int arr[], int n) {
int lastSwapPos = n - 1;
while (lastSwapPos > 0) {
int currentSwapPos = 0;
for (int j = 0; j < lastSwapPos; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
currentSwapPos = j;
}
}
lastSwapPos = currentSwapPos;
}
}
实际应用:学生成绩排序
#include <iostream>
#include <string>
using namespace std;
struct Student {
string name;
double score;
};
void sortByScore(Student students[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (students[j].score < students[j + 1].score) {
Student temp = students[j];
students[j] = students[j + 1];
students[j + 1] = temp;
}
}
}
}
int main() {
Student students[] = {
{"张三", 85.5},
{"李四", 92.0},
{"王五", 78.5},
{"赵六", 95.0}
};
int n = 4;
cout << "=== 成绩排名 ===" << endl;
sortByScore(students, n);
for (int i = 0; i < n; i++) {
cout << (i+1) << ". ";
cout << students[i].name << ": ";
cout << students[i].score << "分" << endl;
}
return 0;
}
🚀 性能分析与优化
时间复杂度详细分析
| 数据规模n |
比较次数 |
近似计算时间 |
| 10 |
45 |
瞬间 |
| 100 |
4,950 |
瞬间 |
| 1,000 |
499,500 |
几毫秒 |
| 10,000 |
49,995,000 |
几百毫秒 |
| 100,000 |
约50亿 |
几分钟 |
性能测试对比
#include <iostream>
#include <chrono>
#include <cstdlib>
using namespace std;
using namespace chrono;
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (minIndex != i) {
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
int main() {
const int SIZE = 5000;
int arr1[SIZE], arr2[SIZE];
for (int i = 0; i < SIZE; i++) {
arr1[i] = arr2[i] = rand() % 10000;
}
auto start1 = high_resolution_clock::now();
bubbleSort(arr1, SIZE);
auto end1 = high_resolution_clock::now();
auto duration1 = duration_cast(end1 - start1);
auto start2 = high_resolution_clock::now();
selectionSort(arr2, SIZE);
auto end2 = high_resolution_clock::now();
auto duration2 = duration_cast(end2 - start2);
cout << "数据规模:" << SIZE << endl;
cout << "冒泡排序耗时:" << duration1.count() << " ms" << endl;
cout << "选择排序耗时:" << duration2.count() << " ms" << endl;
return 0;
}
📝 实战练习
📝 理解测试
对于已经有序的数组 [1, 2, 3, 4, 5],哪种排序算法更快?
选择答案查看解析...
💻 综合挑战
题目:实现一个完整的排序程序:
1. 输入n个整数
2. 分别用冒泡排序和选择排序进行排序
3. 输出排序结果
4. 统计两种排序的比较次数和交换次数
5. 比较两种算法的性能差异
点击"生成代码框架"查看提示...