使用场景
了解各个排序的特性,针对排序好的序列进行查找
稳定排序
C 实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define swap(a, b) { \
a ^= b; b ^= a; a ^= b; \
}
// 宏书写,方便测试
#define TEST(arr, n, func, args...) { \
int *num = (int *) malloc(sizeof(int) * n); \
memcpy(num, arr, sizeof(int) * n); \
output(num, n); \
printf("%s= ", #func); \
func(args); \
output(num, n); \
free(num); \
}
// O(N^2)
void insert_sort(int *num, int n) {
for (int i = 1; i < n; ++i) {
for (int j = i; j > 0 && num[j] < num[j - 1]; --j) {
swap(num[j], num[j - 1]);
}
}
return ;
}
// O(N^2)
void bubble_sort(int *num, int n) {
int times = 1;
for (int i = 1; i < n && times; i++) {
// 帮助提前退出
times = 0;
for (int j = 0; j < n - i; ++j) {
if (num[j] <= num[j + 1]) continue;
swap(num[j], num[j + 1]);
times++;
}
}
return;
}
// O(NlgN) S(N)
void merge_sort(int *num, int l, int r) {
// 递归条件
if (r - l <= 1) {
if (r - l == 1 && num[r] < num[l]) {
swap(num[r], num[l]);
}
return;
}
int mid = (l + r) / 2;
merge_sort(num, l, mid);
merge_sort(num, mid + 1, r);
int *temp = (int *) malloc(sizeof(int) * (r - l + 1));
int p1 = l, p2 = mid + 1, k = 0;
// 左右两块肯定都没到头
while (p1 <= mid || p2 <= r) {
if (p2 > r || (p1 <= mid && num[p1] < num[p2])) {
temp[k++] = num[p1++];
} else {
temp[k++] = num[p2++];
}
}
memcpy(num + l, temp, sizeof(int) * (r - l + 1));
free(temp);
return;
}
void randint(int *num, int n) {
while (n--) num[n] = rand() % 100;
return;
}
void output(int *num, int n) {
printf("[");
for (int i = 0; i < n; ++i) {
printf("%d ", num[i]);
}
printf("]\n");
return;
}
int main() {
// 演示
srand(time(0));
#define max_n 20
int arr[max_n];
randint(arr, max_n);
TEST(arr, max_n, insert_sort, num, max_n);
TEST(arr, max_n, bubble_sort, num, max_n);
TEST(arr, max_n, merge_sort, num, 0, max_n - 1);
#undef max_n
return 0;
}
C++ 实现
class Vector {
private:
int size, length;
int *data;
public:
Vector(int input_size) {
size = input_size;
length = 0;
data = new int[size];
}
~Vector() {
delete[] data;
}
bool insert(int loc, int value) {
if (loc < 0 || loc > length) {
return false;
}
if (length >= size) {
return false;
}
for (int i = length; i > loc; --i) {
data[i] = data[i - 1];
}
data[loc] = value;
length++;
return true;
}
void print() {
for (int i = 0; i < length; ++i) {
if (i > 0) {
cout << " ";
}
cout << data[i];
}
cout << endl;
}
void insert_sort() {
for (int i = 0; i < length; ++i) {
for (int j = i - 1; j >= 0; --j) {
if (data[j] > data[j + 1]) {
swap(data[j], data[j + 1]);
} else {
break;
}
}
}
}
void bubble_sort() {
for (int i = 0; i < length - 1; ++i) {
bool swapped = false;
for (int j = 0; j < length - i - 1; ++j) {
if (data[j] > data[j + 1]) {
swap(data[j], data[j + 1]);
swapped = true;
}
}
if (swapped == false) {
break;
}
}
}
void merge_sort(int l, int r) {
if (l == r) {
return;
}
int mid = (l + r) / 2;
merge_sort(l, mid);
merge_sort(mid + 1, r);
int x = l, y = mid + 1, loc = l;
while (x <= mid || y <= r) {
if (x <= mid && (y > r || data[x] <= data[y])) {
temp[loc] = data[x];
x++;
} else {
temp[loc] = data[y];
y++;
}
loc++;
}
for (int i = l; i <= r; ++i) {
data[i] = temp[i];
}
}
}
不稳定排序
排序后原来等值元素前后顺序不一定保持
C 实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define swap(a, b) { \
__typeof(a) __temp = a; \
a = b; b = __temp; \
}
#define TEST(arr, n, func, args...) { \
int *num = (int *) malloc(sizeof(int) * n); \
memcpy(num, arr, sizeof(int) * n); \
output(num, n); \
printf("%s=", #func); \
func(args); \
output(num, n); \
free(num); \
}
// O(N^2)
void select_sort(int *num, int n) {
for (int i = 0; i < n - 1; ++i) {
int ind = i;
for (int j = i + 1; j < n; ++j) {
if (num[ind] > num[j]) ind = j;
}
swap(num[i], num[ind]);
}
return;
}
// O(NlgN) S(lgN) 使用栈空间
// 选头个元素为枢轴,逆序的情况下会退化,时间复杂度 O(N^2)
// 枢轴可以选随机
void quick_sort(int *num, int l, int r) {
if (l > r) return;
int x = l, y = r, z = num[x];
while (x < y) {
while(x < y && num[y] > z) y--;
if (x < y) num[x++] = num[y];
while(x < y && num[x] < z) x++;
if (x < y) num[y--] = num[x];
}
num[x] = z;
quick_sort(num, l, x - 1);
quick_sort(num, x + 1, r);
return;
}
// 快速排序另外一种写法,逆序情况下优化
void quick_sort(int *num, int l, int r) {
while (l < r) {
int x = l, y = r, z = num[(l + r) / 2];
do {
while (x <= y && num[x] < z) x++;
while (x <= y && num[y] > z) y--;
if (x <= y) {
swap(num[x], num[y]);
x++, y--;
}
} while (x <= y);
quick_sort(num, x, r); // 这里右边继续划分
r = y; // 左边继续划分
}
return ;
}
void randint(int *num, int n) {
while (n--) num[n] = rand() % 100;
return;
}
void output(int *num, int n) {
printf("[");
for (int i = 0; i < n; ++i) {
printf("%d ", num[i]);
}
printf("]\n");
return;
}
int main() {
srand(time(0));
#define max_n 20
int arr[max_n];
randint(arr, max_n);
TEST(arr, max_n, select_sort, num, max_n);
TEST(arr, max_n, quick_sort, num, 0, max_n - 1);
#undef max_n
return 0;
}
C++ 实现
class Vector {
private:
int size, length;
int *data;
public:
Vector(int input_size) {
size = input_size;
length = 0;
data = new int[size];
}
~Vector() {
delete[] data;
}
bool insert(int loc, int value) {
if (loc < 0 || loc > length) {
return false;
}
if (length >= size) {
return false;
}
for (int i = length; i > loc; --i) {
data[i] = data[i - 1];
}
data[loc] = value;
length++;
return true;
}
void print() {
for (int i = 0; i < length; ++i) {
if (i > 0) {
cout << " ";
}
cout << data[i];
}
cout << endl;
}
void select_sort() {
int temp;
for (int i = 0; i < length - 1; ++i) {
temp = i;
for (int j = i + 1; j < length; ++j) {
if (data[temp] > data[j]) {
temp = j;
}
}
if (i != temp) {
swap(data[i], data[temp]);
}
}
}
void quick_sort(int left, int right) {
if (left > right) {
return;
}
int pivot = data[left], low = left, high = right;
while (low < high) {
while (low < high && data[high] >= pivot) {
high--;
}
data[low] = data[high];
while (low < high && data[low] <= pivot) {
low++;
}
data[high] = data[low];
}
data[low] = pivot;
quick_sort(left, low - 1);
quick_sort(low + 1, right);
}
};
查找
主要是二分查找,1100 情况(小于目标元素的最大值),0011 情况 (大于目标元素的最小值)
三分查找对于凸性函数序列找最大值或者最小值
C 语言实现
#include <stdio.h>
#define P(func) { \
printf("%s = %d\n", #func, func); \
}
int binary_search1(int *num, int n, int x) {
int head = 0, tail = n - 1, mid;
while (head <= tail) {
mid = (head + tail) >> 1;
if (num[mid] == x) return mid;
if (num[mid] < x) head = mid + 1;
else tail = mid - 1;
}
return -1;
}
// 111111000000
int binary_search2(int *num, int n) {
int head = -1, tail = n - 1, mid;
while (head < tail) {
mid = (head + tail + 1) >> 1;
if (num[mid] == 1) head = mid;
else tail = mid - 1;
}
return head;
}
// 000000111111
int binary_search3(int *num, int n) {
int head = 0, tail = n, mid;
while (head < tail) {
mid = (head + tail) / 2;
if (num[mid] == 1) tail = mid;
else head = mid + 1;
}
return head == n ? -1 : head;
}
int main() {
int arr1[10] = {1,3,5,7,9,11,13,17,19,20};
int arr2[10] = {1,1,1,1,0,0,0,0,0,0};
int arr3[10] = {0,0,0,0,0,1,1,1,1,1};
P(binary_search1(arr1, 10, 7));
P(binary_search2(arr2, 10));
P(binary_search3(arr3, 10));
return 0;
}
C++ 实现
class Vector {
private:
int size, length;
int *data;
public:
Vector(int input_size) {
size = input_size;
length = 0;
data = new int[size];
}
~Vector() {
delete[] data;
}
bool insert(int loc, const int &value) {
if (loc < 0 || loc > length) {
return false;
}
if (length >= size) {
return false;
}
for (int i = length; i > loc; --i) {
data[i] = data[i - 1];
}
data[loc] = value;
length++;
return true;
}
// 三分查找
int find_max() {
int left = 0, right = length - 1;
while (right - left >= 2) {
int m1 = left + (right - left) / 3;
int m2 = right - (right - left + 2) / 3;
// 结合图
if (data[m1] >= data[m2]) {
right = m2;
} else {
left = m1 + 1;
}
}
if (data[left] > data[right]) {
return left;
} else {
return right;
}
}
};