从今天开始总结数据结构的相关知识,基础算法分为三个部分。顺序为基础算法-排序,基础算法-(高精度,前缀和与差分),基础算法-双指针。
先从最基础的排序开始,建议是首先理解原理,再把算法模版背下来。
一下是总结,相关的原理链接,动图演示,代码都已经整理好了。包括冒泡排序,选择排序,插入排序,快速排序,归并排序,堆排序。
目录
华为是acm模式,所以需要输入输出,假设输入的数组是不定长的(对输入输出不熟悉的参考第一篇文章哦秋招华为机试准备1(c++的输入和输出)-CSDN博客)
int main() {
vector<int> arr;
int nums;
cout << "Enter numbers to sort (end with newline): ";
while (cin >> nums) {
arr.push_back(nums);
if (cin.peek() == '\n') break;
}
bubbleSort(arr.data(), arr.size()); //替换为相对应的排序函数
cout << "Sorted array: ";
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << " ";
}
return 0;
}
Enter numbers to sort(end with newline) : 5 6 8 9 7 2 4 66 55 44 3 0 0 1 1
Sorted array : 0 0 1 1 2 3 4 5 6 7 8 9 44 5
冒泡排序
冒泡排序是一种简单的排序算法,通过重复比较相邻元素并交换它们的位置来排序。
详细的原理说明:【排序算法】史上最通俗易懂的【冒泡排序】详解-CSDN博客
动图演示:
代码模板 (如果有一次没有发生交换,说明数组已经排序好,提前退出循环)
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int flag = 0;
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr[j], arr[j + 1]);
flag = 1;
}
}
if (flag == 0) {
break; // No swaps means the array is sorted
}
}
}
选择排序
选择排序通过每次选择未排序部分的最小元素并将其放到已排序部分的末尾。
详细原理说明:【排序算法】选择排序的全面剖析(含详细图解)-CSDN博客
动图演示:
代码模板
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;
}
}
std::swap(arr[i], arr[minIndex]);
}
}
插入排序
插入排序通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
详细原理说明:排序算法——直接插入排序(图文超详细!)-CSDN博客
动图演示:
代码模板
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i-1;
while (j >= 0 && arr[j] > key) { //边界问题要处理,j--可能等于-1
arr[j+1] = arr[j];
j--;
}
arr[j+1] = key;
}
}
快速排序
快速排序是一种分治算法,通过选择一个“基准”元素将数组分为两部分,一部分小于基准,一部分大于基准,然后递归排序。(*快速排序可以迅速确定某个元素在所有元素中的位置)
详细原理说明:快速排序算法—图文详解,一篇就够了!-CSDN博客
动图演示:
代码模板(Acwing学的ycx)
void quick_sort(int q[], int l, int r)
{
if (l >= r) return; //递归退出条件
int i = l - 1, j = r + 1, x = q[l + r >> 1]; //取数组拍在中间的数作为基准
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
//main里面:quick_sort(arr.data(),0,arr.size()-1);
归并排序
归并排序也是一种分治算法,通过将数组分成两半,递归排序后再合并。(我的理解是将数组按照二叉树的形状全部分开,再从尾部向根部一步步合起来)
详细原理说明:排序——归并排序(Merge sort)-CSDN博客
动图演示:
代码模板(依旧是背的y总的模板)
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
堆排序
堆排序利用堆数据结构进行排序,通过构建最大堆并反复提取最大元素。(涉及二叉树的数据结构,在后面树和图的地方会重新温习一遍)
详细原理说明:堆排序详细图解(通俗易懂)-CSDN博客
动图演示:
代码模板
void heapify(int arr[], int n, int i) {
int largest = i;
int l = 2*i + 1;
int r = 2*i + 2;
if (l < n && arr[l] > arr[largest]) {
largest = l;
}
if (r < n && arr[r] > arr[largest]) {
largest = r;
}
if (largest != i) {
std::swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}
void heapSort(int arr[], int n) {
for (int i = n/2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
for (int i = n-1; i > 0; i--) {
std::swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
STL中的排序算法
C++标准库提供了std::sort
函数,通常基于快速排序或混合算法实现(如果题目的重点不在排序直接用sort就行)。
#include <algorithm>
#include <vector>
int main() {
std::vector<int> arr = {5, 2, 9, 1, 5, 6};
std::sort(arr.begin(), arr.end());
return 0;
}
时间和空间复杂度:
基数排序,桶排序之类的在题目中少见,就不列出来了。