1 常见算法
1.1 排序算法
1.1.1 冒泡算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
void maopao(int arr[], int length) { int temp; for(int i=0; i<length; i++) { for(int j=0; j<length-i-1; j++) { if(arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } }
|
1.1.2 快速排序

上图参考视频链接:快速排序 - 哔哩哔哩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
int fenqu(int arr[], int left, int right) { int temp = 0; int pivot = arr[right]; int slow = left; int fast = left; while(fast < right) { if(arr[fast] < pivot) { temp = arr[slow]; arr[slow] = arr[fast]; arr[fast] = temp; slow++; } fast++; } temp = arr[slow]; arr[slow] = arr[right]; arr[right] = temp; return slow; }
void kuaisu(int arr[], int left, int right) { if(left < right) { int point = fenqu(arr, left, right); kuaisu(arr, left, point-1); kuaisu(arr, point+1, right); } }
|
1.1.3 堆排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
void dagendui(int arr[], int length, int index) { int largest = index; int left = 2 * index + 1; int right = 2 * index + 2; if (left < length && arr[left] > arr[largest]) largest = left; if (right < length && arr[right] > arr[largest]) largest = right; if (largest != index) { int temp = arr[largest]; arr[largest] = arr[index]; arr[index] = temp; dagendui(arr, length, largest); } }
void dui(int arr[], int length) { for (int i = length / 2 - 1; i >= 0; i--) dagendui(arr, length, i); for (int i = length - 1; i > 0; i--) { int temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; dagendui(arr, i, 0); } }
|
对我来说堆排序的难点主要是构建大根堆函数dagendui()中的逻辑:

上面的代码中核心思想是:
- 进入函数,首先假设待调整节点的索引
i就是最大值对应的索引largest = i;
- 然后计算左右子节点的索引;
- 判断左子节点的索引是否小于数组长度,再判断左子节点对应的值是否大于最大值索引
largest对应的值,如果大于,则更新最大值对应的索引largest = 2*i+1(这里不进行值的交换,只更新索引);
- 判断右子节点的索引是否小于数组长度,再判断右子节点对应的值是否大于最大值索引
largest对应的值,如果大于,则更新最大值对应的索引largest = 2*i+2(这里不进行值的交换,只更新索引);
- 判断最大值对应的索引
largest是否还等于i,若不等于,说明左右子节点有比待调整节点对应的值还大的,根据大根堆的原则,需要进行调整,这时候就之间交换largest索引和i索引对应的值即可;
- 最后不要忘了:递归调整受影响的子树(因为交换元素后,交换下来的元素有可能在以自己为根节点的子树上不是最大堆)。
1.1.4 归并排序
(一)归并排序算法源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| #include <stdio.h> #include <stdlib.h>
void merge(int arr[], int left, int mid, int right) { int len_left = mid - left + 1; int len_right = right - mid;
int* left_arr = (int*)malloc(len_left * sizeof(int)); int* right_arr = (int*)malloc(len_right * sizeof(int));
for (int i = 0; i < len_left; i++) left_arr[i] = arr[left + i];
for (int j = 0; j < len_right; j++) right_arr[j] = arr[mid + 1 + j];
int i = 0; int j = 0; int k = left;
while (i < len_left && j < len_right) { if (left_arr[i] <= right_arr[j]) { arr[k] = left_arr[i]; i++; } else { arr[k] = right_arr[j]; j++; } k++; }
while (i < len_left) { arr[k] = left_arr[i]; i++; k++; }
while (j < len_right) { arr[k] = right_arr[j]; j++; k++; }
free(left_arr); free(right_arr); }
void merge_sort(int arr[], int left, int right) { if (left < right) { int mid = left + (right - left) / 2;
merge_sort(arr, left, mid);
merge_sort(arr, mid + 1, right);
merge(arr, left, mid, right); } }
void print_array(int arr[], int size) { for (int i = 0; i < size; i++) printf("%d ", arr[i]); printf("\n"); }
int main() { int arr[] = {38, 27, 43, 3, 9, 82, 10}; int size = sizeof(arr) / sizeof(arr[0]);
printf("排序前的数组:"); print_array(arr, size);
merge_sort(arr, 0, size - 1);
printf("排序后的数组:"); print_array(arr, size);
return 0; }
|
归并排序的两个重要函数:
- 合并两个有序数组函数
void merge(int arr[], int left, int mid, int right),这个函数的逻辑还比较简单;
- 归并排序主函数
void merge_sort(int arr[], int left, int right),这个函数的逻辑感觉确实有点难理解,实在不行就硬记吧,代码量不大
- Step1:计算中点
- Step2:递归排序左子数组
- Step3:递归排序右子数组
- Step4:合并排序后的左右子数组
(二)归并算法用于链表排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| typedef struct ListNode { int val; struct ListNode *next; }ListNode;
ListNode* MergeLink(ListNode* start, ListNode* mid) { ListNode* head = (ListNode*)malloc(sizeof(ListNode)); ListNode* reslut = head; while(start && mid) { if(start->val < mid->val) { head->next = start; start = start->next; } else { head->next = mid; mid = mid->next; } head = head->next; } if(start) head->next = start; if(mid) head->next = mid; return reslut->next; }
ListNode* sortList(ListNode* head) { if(head == NULL || head->next == NULL) return head; ListNode* slow = head; ListNode* fast = head->next; while(fast && fast->next) { slow = slow->next; fast = fast->next->next; } ListNode* start = head; ListNode* mid = slow->next; slow->next = NULL;
start = sortList(start); mid = sortList(mid); return MergeLink(start, mid); }
|
参考链接:【LeetCode 148】排序链表 - 华南溜达虎 - 哔哩哔哩
1.2 二叉树的遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #include <stdio.h> #include <stdlib.h>
typedef struct TreeNode { int value; struct TreeNode *left; struct TreeNode *right; } TreeNode;
TreeNode* createNode(int val) { TreeNode* ptreenode = (TreeNode*)malloc(sizeof(TreeNode)); ptreenode->value = val; ptreenode->left = NULL; ptreenode->right = NULL; return ptreenode; }
void preOrderTraversal(TreeNode *cur) { if(!cur) return; printf("%d ", cur->value); preOrderTraversal(cur->left); preOrderTraversal(cur->right); }
void milOrderTraversal(TreeNode *cur) { if(!cur) return; milOrderTraversal(cur->left); printf("%d ", cur->value); milOrderTraversal(cur->right); }
void postOrderTraversal(TreeNode *cur) { if(!cur) return; postOrderTraversal(cur->left); postOrderTraversal(cur->right); printf("%d ", cur->value); }
int main() {
TreeNode *root = createNode(1); root->left = createNode(2); root->right = createNode(3); root->left->left = createNode(4); root->left->right = createNode(5); root->right->left = createNode(6); root->right->right = createNode(7); root->right->right->left = createNode(8); root->right->right->right = createNode(9); printf("前序遍历顺序: "); preOrderTraversal(root); printf("\n中序遍历顺序: "); milOrderTraversal(root); printf("\n后序遍历顺序: "); postOrderTraversal(root); printf("\n"); return 0; }
|