排序算法
基础排序
选择排序
template<typename T>
void selectionSort(T arr[], int n) {
int minIndex = 0;
for (int i = 0; i < n - 1; ++i) {
minIndex = i;
for (int j = i + 1; j < n; ++j)
if (arr[j] < arr[minIndex]) minIndex = j;
swap(arr[i], arr[minIndex]);
}
}
插入排序
template<typename T>
void insertionSort(T arr[], int n) {
for (int i = 1; i < n; ++i) {
T e = arr[i];
int j;
for (j = i; j >= 1 && arr[j - 1] > e; --j)
arr[j] = arr[j - 1];
arr[j] = e;
}
}
插入排序(2)
template<typename T>
void insertionSort(T arr[], int l, int r) {
for (int i = l + 1; i <= r; ++i) {
T e = arr[i];
int j;
for (j = i; j > l && arr[j - 1] > e; --j)
arr[j] = arr[j - 1];
arr[j] = e;
}
}
冒泡排序
template<typename T>
void bubbleSort(T 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])
swap(arr[j], arr[j + 1]);
}
冒泡排序(2)
template<typename T>
void bubbleSort2(T arr[], int n) {
bool swapped;
do {
swapped = false;
for (int i = 1; i < n; i++)
if (arr[i - 1 ] > arr[i]) {
swap(arr[i - 1], arr[i]);
swapped = true;
}
n--;
} while (swapped);
}
希尔排序
template<typename T>
void shellSort(T arr[], int n) {
int h = 1;
while (h < n / 3)
h = 3 * h + 1;
while (h >= 1) {
for (int i = h; i < n; i++) {
T e = arr[i];
int j;
for (j = i; j >= h && e < arr[j - h]; j -= h)
arr[j] = arr[j - h];
arr[j] = e;
}
h /= 3;
}
}
高级排序
归并排序
template<typename T>
void mergeSort(T arr[], int n) {
__mergeSort(arr, 0, n - 1);
}
template<typename T>
void __mergeSort(T arr[], int l, int r) {
if (l >= r) return;
int mid = l + (r - l) / 2;
__mergeSort(arr, l, mid);
__mergeSort(arr, mid + 1, r);
if (arr[mid] > arr[mid + 1])
__merge(arr, l, mid, r);
}
template<typename T>
void __merge(T arr[], int l, int mid, int r) {
T aux[r - l + 1];
for (int i = l; i <= r; ++i)
aux[i - l] = arr[i];
int i = l, j = mid + 1;
for (int k = l; k <= r; ++k) {
if (i > mid) {
arr[k] = aux[j - l];
j++;
} else if (j > r) {
arr[k] = aux[i - l];
i++;
} else if (aux[i - l] < aux[j - l]) {
arr[k] = aux[i - l];
i++;
} else {
arr[k] = aux[j - l];
j++;
}
}
}
归并排序(2)——自底向上
template<typename T>
void mergeSortBU(T arr[], int n) {
for (int sz = 1; sz <= n; sz += sz)
for (int i = 0; i + sz < n; i += sz + sz)
__merge(arr, i, i+sz-1, min(i+sz+sz-1, n-1));
}
快速排序—-单路快排
template<typename T>
void quickSort(T arr[], int n) {
srand((unsigned int) time(NULL));
__quickSort(arr, 0, n - 1);
}
template<typename T>
void __quickSort(T arr[], int l, int r) {
if (r - l <= 15) {
insertionSort(arr, l, r);
return;
}
int p = __partition(arr, l, r);
__quickSort(arr, l, p - 1);
__quickSort(arr, p + 1, r);
}
template<typename T>
int __partition(T arr[], int l, int r) {
swap(arr[l], arr[rand() % (r - l + 1) + l]);
T v = arr[l];
int j = l;
for (int i = l + 1; i <= r; ++i) {
if (arr[i] < v) {
swap(arr[j + 1], arr[i]);
j++;
}
}
swap(arr[l], arr[j]);
return j;
}
快速排序—-双路快排
template<typename T>
void quickSort2Ways(T arr[], int n) {
srand((unsigned int) time(NULL));
__quickSort2Ways(arr, 0, n - 1);
}
template<typename T>
void __quickSort2Ways(T arr[], int l, int r) {
if (r - l <= 15) {
insertionSort(arr, l, r);
return;
}
int p = __partition2Ways(arr, l, r);
__quickSort2Ways(arr, l, p - 1);
__quickSort2Ways(arr, p + 1, r);
}
template<typename T>
int __partition2Ways(T arr[], int l, int r) {
swap(arr[l], arr[rand() % (r - l + 1) + l]);
T v = arr[l];
int i = l + 1, j = r;
while (true) {
while (i <= r && arr[i] < v) i++;
while (j >= l + 1 && arr[j] > v) j--;
if (i > j) break;
swap(arr[i], arr[j]);
i++;
j--;
}
swap(arr[l], arr[j]);
return j;
}
快速排序—-三路快排
template<typename T>
void quickSort3Ways(T arr[], int n) {
srand((unsigned int) time(NULL));
__quickSort3Ways(arr, 0, n - 1);
}
template<typename T>
void __quickSort3Ways(T arr[], int l, int r) {
if (r - l <= 15) {
insertionSort(arr, l, r);
return;
}
swap(arr[l], arr[rand() % (r - l + 1) + l]);
T v = arr[l];
int lt = l;
int gt = r + 1;
int i = l + 1;
while (i < gt)
if (arr[i] < v) {
swap(arr[i], arr[lt + 1]);
lt++;
i++;
} else if (arr[i] > v) {
swap(arr[i], arr[gt - 1]);
gt--;
} else
i++;
swap(arr[l], arr[lt]);
__quickSort3Ways(arr, l, lt - 1);
__quickSort3Ways(arr, gt, r);
}
计数排序
void countingSort(int arr[], int ret[], int n, int upperBound) {
int len = upperBound + 1;
int *C = new int[len];
for (int i = 0; i < len; ++i)
C[i] = 0;
for (int i = 0; i < n; ++i)
C[arr[i]]++;
for (int i = 1; i < len; ++i)
C[i] += C[i - 1];
for (int i = n - 1; i >= 0; --i) {
ret[C[arr[i]] - 1] = arr[i];
C[arr[i]]--;
}
delete[] C;
}
堆排序(1)
template<typename Item>
class MaxHeap {
private:
Item *data;
int count;
int capacity;
void siftUp(int k) {
while (k > 1 && data[k / 2] < data[k]) {
swap(data[k / 2], data[k]);
k /= 2;
}
}
void siftDown(int k) {
while (2 * k <= count) {
int j = 2 * k;
if (j + 1 <= count && data[j + 1] > data[j])
j += 1;
if (data[k] >= data[j]) break;
swap(data[k], data[j]);
k = j;
}
}
public:
MaxHeap(int capacity) {
data = new Item[capacity + 1];
count = 0;
this->capacity = capacity;
}
MaxHeap(Item arr[], int n) {
data = new Item[n + 1];
capacity = n;
copy(arr, arr + n, data + 1);
count = n;
for (int i = count / 2; i >= 1; --i) siftDown(i);
}
int size() { return count; }
bool empty() { return count == 0; }
void insert(Item item) {
assert(count + 1 <= capacity);
data[++count] = item;
siftUp(count);
}
Item extractMax() {
assert(count > 0);
Item ret = data[1];
swap(data[1], data[count--]);
siftDown(1);
return ret;
}
~MaxHeap() { delete[] data; }
};
template<typename T>
void heapSort(T arr[], int n) {
MaxHeap<T> maxHeap = MaxHeap<int>(arr, n);
for (int i = n - 1; i >= 0; --i)
arr[i] = maxHeap.extractMax();
}
堆排序(2)—-原地堆排序
template<typename T>
void heapSort(T arr[], int n) {
for (int i = (n - 1) / 2; i >= 0; --i)
__siftDown(arr, n, i);
for (int i = n - 1; i > 0; --i) {
swap(arr[0], arr[i]);
__siftDown(arr, i, 0);
}
}
template<typename T>
void __siftDown(T arr[], int n, int k) {
while (2 * k + 1 < n) {
int j = 2 * k + 1;
if (j + 1 < n && arr[j + 1] > arr[j])
j += 1;
if (arr[k] >= arr[j])break;
swap(arr[k], arr[j]);
k = j;
}
}
二叉树遍历
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
层序遍历
void levelOrderTraversal(TreeNode *root) {
if (root == NULL)
return;
TreeNode *p = root;
queue<TreeNode *> queue;
queue.push(p);
while (!queue.empty()) {
p = queue.front();
cout << p->val << endl;
queue.pop();
if (p->left)
queue.push(p->left);
if (p->right)
queue.push(p->right);
}
}
前序遍历(1)—-递归
void preorderTraversal(TreeNode *root) {
if (root) {
cout << root->val << endl;
preorderTraversal(root->left);
preorderTraversal(root->right);
}
}
前序遍历(2)—-非递归经典
void preorderTraversal(TreeNode *root) {
if (root == NULL)
return;
TreeNode *p = root;
stack<TreeNode *> stack;
while (p || !stack.empty()) {
if (p) {
stack.push(p);
cout << p->val << endl;
p = p->left;
} else {
p = stack.top();
stack.pop();
p = p->right;
}
}
}
中序遍历(1)—-递归
void inorderTraversal(TreeNode *root) {
if (root) {
inorderTraversal(root->left);
cout << root->val << endl;
inorderTraversal(root->right);
}
}
中序遍历(2)—-非递归经典
void inorderTraversal(TreeNode *root) {
if (root == NULL)
return;
stack<TreeNode *> stack;
TreeNode *p = root;
while (p || !stack.empty()) {
if (p) {
stack.push(p);
p = p->left;
} else {
p = stack.top();
stack.pop();
cout << p->val << endl;
p = p->right;
}
}
}
后序遍历(1)—-递归
void postorderTraversal(TreeNode *root) {
if (root) {
inorderTraversal(root->left);
inorderTraversal(root->right);
cout << root->val << endl;
}
}
后序遍历(2)—-非递归经典
void postorderTraversal(TreeNode *root) {
if (root == NULL)
return;
stack<TreeNode *> stack;
TreeNode *p = root;
TreeNode *r = NULL;
while (p || !stack.empty()) {
if (p) {
stack.push(p);
p = p->left;
} else {
p = stack.top();
if (p->right && p->right != r) {
p = p->right;
stack.push(p);
p = p->left;
} else {
stack.pop();
cout << p->val << endl;
r = p;
p = NULL;
}
}
}
}
二分查找法
template<typename T>
int binarySearch(T arr[], int n, T target) {
int l = 0, r = n - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (target == arr[mid])
return mid;
else if (target > arr[mid])
l = mid + 1;
else
r = mid - 1;
}
return -1;
}
二分查找法(2)—-递归
template<typename T>
int binarySearch2(T arr[], int n, T target) {
return __search(arr, 0, n - 1, target);
}
template<typename T>
int __search(T arr[], int l, int r, T target) {
if (l > r) return -1;
int mid = (l + r) / 2;
if (arr[mid] == target)
return mid;
else if (target > arr[mid])
return __search(arr, mid + 1, r, target);
else
return __search(arr, l, mid - 1, target);
}
二分搜索树
搜索
TreeNode *searchBST(TreeNode *root, int val) {
if (root == NULL)
return NULL;
if (val > root->val)
return searchBST(root->right, val);
else if (val < root->val)
return searchBST(root->left, val);
return root;
}
### 查找最小节点
```cpp
TreeNode *minimum(TreeNode *node) {
if (node == NULL)
return NULL;
if (!node->left)
return node;
return minimum(node->left);
}
最近公共祖先
TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p,
TreeNode *q) {
if (root == NULL)
return NULL;
if (p->val > root->val && q->val > root->val)
return lowestCommonAncestor(root->right, p, q);
if (p->val < root->val && q->val < root->val)
return lowestCommonAncestor(root->left, p, q);
return root;
}
插入
TreeNode *insertIntoBST(TreeNode *root, int val) {
if (root == NULL)
return new TreeNode(val);
if (val > root->val)
root->right = insertIntoBST(root->right, val);
else if (val < root->val)
root->left = insertIntoBST(root->left, val);
return root;
}
删除最小节点
TreeNode *deleteMinNode(TreeNode *root) {
if (root == NULL)
return NULL;
if (root->left == NULL) {
TreeNode *delNode = root;
root = root->right;
delete delNode;
} else
root->left = deleteMinNode(root->left);
return root;
}
删除任意节点
TreeNode *deleteNode(TreeNode *root, int key) {
if (root == NULL)
return NULL;
if (key > root->val)
root->right = deleteNode(root->right, key);
else if (key < root->val)
root->left = deleteNode(root->left, key);
else {
if (root->left && root->right) {
TreeNode *minNode = minimum(root->right);
root->val = minNode->val;
root->right = deleteNode(root->right, root->val);
} else {s
TreeNode *delNode = root;
if (!root->left)
root = root->right;
else
root = root->left;
delete delNode;
}
}
return root;
}
并查集
class UnionFind {
private:
int *parent;
int *rank;
int count;
public:
UnionFind(int count) {
parent = new int[count];
rank = new int[count];
this->count = count;
for (int i = 0; i < count; ++i) {
parent[i] = i;
rank[i] = 1;
}
}
int find(int p) {
assert(p >= 0 && p < count);
while (p != parent[p]) {
parent[p] = parent[parent[p]];
p = parent[p];
}
return p;
}
bool isConnected(int p, int q) { return find(p) == find(q); }
void unionElements(int p, int q) {
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) return;
if (rank[pRoot] < rank[qRoot]) parent[pRoot] = qRoot;
else if (rank[qRoot] < rank[pRoot]) parent[qRoot] = pRoot;
else {
parent[pRoot] = qRoot;
rank[qRoot] += 1;
}
}
~UnionFind() {
delete[] parent;
delete[] rank;
}
};
图
const int MAX_N = 100;
int G[MAX_N][MAX_N];
bool visited[MAX_N];
深度优先搜索
void dfs() {
fill(visited, visited + MAX_N, false);
for (int u = 0; u < n; u++)
if (!visited[u])
dfs_visit(u);
}
深度优先搜索(递归实现)
void dfs_visit(int u) {
visited[u] = true;
cout << u << " ";
for (int v = 0; v < n; v++)
if (G[u][v] && !visited[v])
dfs_visit(v);
}
深度优先搜索(栈实现 1)
void dfs_visit(int u) {
stack<int> S;
S.push(u);
visited[u] = true;
while (!S.empty()) {
u = S.top();
cout << u << " ";
int v;
for (v = 0; v < n; ++v)
if (G[u][v] && !visited[v])
break;
if (v < n) {
S.push(v);
visited[v] = true;
} else
S.pop();
}
}
深度优先搜索(栈实现 2)
void dfs_visit(int u) {
stack<int> S;
S.push(u);
visited[u] = true;
while (!S.empty()) {
u = S.top();
S.pop();
cout << u << " ";
for (int v = 0; v < n; ++v) {
if (G[u][v] && !visited[v]) {
S.push(v);
visited[v] = true;
}
}
}
}
广度优先搜索
void bfs() {
fill(visited, visited + n, false);
for (int u = 0; u < n; u++)
if (!visited[u])
bfs_visit(u);
}
void bfs_visit(int u) {
queue<int> q;
q.push(u);
visited[u] = true;
cout << u << " ";
while (!q.empty()) {
u = q.front();
q.pop();
for (int v = 0; v < n; v++)
if (G[u][v] && !visited[v]) {
q.push(v);
visited[v] = true;
cout << v << " ";
}
}
}
最小生成树(Prim 算法)
int prim() {
bool intree[MAX_N];
int dist[MAX_N];
int parent[MAX_N];
fill(intree, intree + n, false);
fill(dist, dist + n, INFINITY);
fill(parent, parent + n, -1);
dist[0] = 0;
while (true) {
int minv = INFINITY;
int u = -1;
for (int v = 0; v < n; v++)
if (!intree[v] && dist[v] < minv) {
minv = dist[v];
u = v;
}
if (u == -1) break;
intree[u] = true;
for (int v = 0; v < n; v++)
if (!intree[v] && G[u][v] != INFINITY)
if (G[u][v] < dist[v]) {
dist[v] = G[u][v];
parent[v] = u;
}
}
int sum = 0;
for (int v = 0; v < n; v++)
if (parent[v] != -1)
sum += G[v][parent[v]];
return sum;
}
最小生成树(Kruskal 算法)
typedef struct Edge {
int s, t, w;
Edge(int s, int t, int w) : s(s), t(t), w(w) {}
bool operator>(const Edge &other) const {
return w > other.w;
}
} Edge;
struct cmp {
bool operator()(const Edge &e1, const Edge &e2) {
return e1.w > e2.w;
}
};
class UnionFind {
……
public:
void unite(int p, int q);
bool connected(int p, int q);
};
int kruskal(int n, vector<Edge> &edges) {
priority_queue<Edge, vector<Edge>, cmp> pq(edges.begin(),
edges.end());
UnionFind uf(n);
int sum = 0;
while (!pq.empty()) {
Edge edge = pq.top();
pq.pop();
int s = edge.s;
int t = edge.t;
int w = edge.w;
if (!uf.connected(s, t)) {
sum += w;
uf.unite(s, t);
}
}
return sum;
}
无权图单源最短路径(广度优先搜索)
void shortest(int s) {
fill(dist, dist + n, -1);
queue<int> queue;
queue.push(s);
dist[s] = 0;
while (!queue.empty()) {
int u = queue.front();
queue.pop();
for (int v = 0; v < n; ++v) {
if (dist[v] == -1 && G[u][v] != INFTY) {
dist[v] = dist[u] + 1;
parent[v] = u;
queue.push(v);
}
}
}
}
有权图单源最短路径(Dijkstra 算法)
void dijkstra() {
bool intree[MAX_N];
int dist[MAX_N];
int parent[MAX_N];
fill(intree, intree + n, false);
fill(dist, dist + n, INFINITY);
fill(parent, parent + n, -1);
dist[0] = 0;
while (true) {
int minv = INFINITY;
int u = -1;
for (int v = 0; v < n; v++)
if (!intree[v] && dist[v] < minv) {
minv = dist[v];
u = v;
}
if (u == -1) break;
intree[u] = true;
for (int v = 0; v < n; v++)
if (!intree[v] && G[u][v] != INFINITY)
if (dist[u] + G[u][v] < dist[v]) {
dist[v] = dist[u] + G[u][v];
parent[v] = u;
}
}
for (int v = 0; v < n; v++)
cout << v << " " << (dist[v] == INFINITY ? -1 : dist[v])
<< endl;
}
有权图单源最短路径(Dijkstra 算法—-堆优化)
vector<pair<int, int> > G[MAX_N];
void dijkstra() {
priority_queue<pair<int, int>, vector<pair<int, int> >,
greater<pair<int, int> > > pq;
bool intree[MAX_N];
int dist[MAX_N];
int parent[MAX_N];
fill(intree, intree + n, false);
fill(dist, dist + n, INFINITY);
fill(parent, parent + n, -1);
dist[0] = 0;
pq.push(make_pair(0, 0));
while (!pq.empty()) {
pair<int, int> f = pq.top();
pq.pop();
int u = f.second;
intree[u] = true;
if (dist[u] < f.first) continue;
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i].first;
if (!intree[v] && dist[u] + G[u][i].second < dist[v]){
dist[v] = dist[u] + G[u][i].second;
pq.push(make_pair(dist[v], v));
parent[v] = u;
}
}
}
for (int v = 0; v < n; v++)
cout << v << " " << (dist[v] == INFINITY ? -1 : dist[v])
<< endl;
}
有权图多源最短路径(Floyd-Warshall 算法)
void floyd() {
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
if (d[i][k] == INFTY) continue;
for (int j = 0; j < n; j++) {
if (d[k][j] == INFTY) continue;
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
}
拓扑排序(广度优先搜索实现)
void bfs(int u) {
queue<int> q;
q.push(u);
visited[u] = true;
while (!q.empty()) {
u = q.front();
q.pop();
cout << u << endl;
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
indeg[v] -= 1;
if (!visited[v] && indeg[v] == 0) {
q.push(v);
visited[v] = true;
}
}
}
}
void top_sort() {
fill(indeg, indeg + n, 0);
fill(visited, visited + n, false);
for (int u = 0; u < n; ++u)
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
indeg[v]++;
}
for (int u = 0; u < n; u++)
if (!visited[u] && indeg[u] == 0)
bfs(u);
}
拓扑排序(深度优先搜索实现)
void dfs(int u) {
visited[u] = true;
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
if (!visited[v])
dfs(v);
}
res.push_front(u);
}
void top_sort() {
fill(visited, visited + n, false);
for (int u = 0; u < n; u++)
if (!visited[u])
dfs(u);
for (int u : res)
cout << u << endl;
}