文章目录
排序算法
1. 冒泡排序
void bubbleSort(int arr[], int n) {
int flag = 0; //标记本轮是否发生元素交换
for (int i = 1; i <= n - 1; i++) {
for (int j = 0; j < n - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 1;
}
}
if (!flag) break;
}
}
2. 选择排序
void selectSort(int arr[], int n) {
for (int i = 0; i < n; i++) {
int min = i; //标记最小元素的下标
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
3. 插入排序
void insertSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int temp = arr[i], j = i;
while (j > 0 && temp < arr[j - 1]) { //元素后移
arr[j] = arr[j - 1];
j--;
}
arr[j] = temp; //插入到对应的位置
}
}
4. 归并排序
4.1 二路归并(递归)
const int maxn = 100;
void merge(int A[], int L1, int R1, int L2, int R2) {
int i = L1, j = L2; // i指向A[L1],j指向A[L2]
int temp[maxn], index = 0; // temp临时存放合并后的序列,index为其元素个数
while (i <= R1 && j <= R2) {
if (A[i] <= A[j]) {
temp[index++] = A[i++];
} else {
temp[index++] = A[j++];
}
}
while (i <= R1) temp[index++] = A[i++]; //将[L1,R1]中剩余元素直接加入序列C
while (j <= R2) temp[index++] = A[j++]; //将[L2,R2]中剩余元素直接加入序列C
for (i = 0; i < index; i++) {
A[L1 + i] = temp[i]; //将合并后的序列赋值返回序列A
}
}
void mergeSort(int A[], int left, int right) {
if (left < right) {
int mid = (left + right) / 2; //取[left,right]中点
mergeSort(A, left, mid); //递归,对左子区间[left,mid]归并排序
mergeSort(A, mid + 1, right); //递归,对右子区间[mid+1,right]归并排序
merge(A, left, mid, mid + 1, right); //将左子区间和右子区间合并
}
}
4.2 二路归并(非递归)
const int maxn = 100;
void merge(int A[], int L1, int R1, int L2, int R2) {
int i = L1, j = L2; // i指向A[L1],j指向A[L2]
int temp[maxn], index = 0; // temp临时存放合并后的序列,index为其元素个数
while (i <= R1 && j <= R2) {
if (A[i] <= A[j]) {
temp[index++] = A[i++];
} else {
temp[index++] = A[j++];
}
}
while (i <= R1) temp[index++] = A[i++]; //将[L1,R1]中剩余元素直接加入序列C
while (j <= R2) temp[index++] = A[j++]; //将[L2,R2]中剩余元素直接加入序列C
for (i = 0; i < index; i++) {
A[L1 + i] = temp[i]; //将合并后的序列赋值返回序列A
}
}
void mergeSort(int A[], int n) {
// step为组内元素个数,step/2为左子区间元素个数
for (int step = 2; step / 2 <= n; step *= 2) {
//每step个元素一组,组内前step/2和后step/2个元素进行合并
for (int i = 0; i < n; i += step) { //对每一组
int mid = i + step / 2 - 1;
if (mid + 1 <= n) { //右子区间存在元素则合并,注意最后一个右子区间
//左子区间为[i,mid],右子区间为[mid+1,min(i+step-1,n)]
merge(A, i, mid, mid + 1, min(i + step - 1, n));
}
}
}
}
4.3 用sort函数替代merge实现
void mergeSort(int A[], int n) {
// step为组内元素个数,step/2为左子区间元素个数
for (int step = 2; step / 2 <= n; step *= 2) {
//每step个元素一组,组内前step/2和后step/2个元素进行合并
for (int i = 0; i < n; i += step) { //对每一组
sort(A + i, A + min(i + step, n + 1));
}
}
}
5. 快速排序
5.1 总是以A[left]为主元
//区间划分
int partition(int A[], int left, int right) {
int temp = A[left]; //以A[left]为主元
while (left < right) {
while (left < right && A[right] > temp) right--; //反复左移right
A[left] = A[right]; //将A[right]移到A[left]
while (left < right && A[left] < temp) left++; //反复右移left
A[right] = A[left]; //将A[left]移到A[right]
}
A[left] = temp; //把temp放到left和right相遇的地方
return left; //返回相遇的下标
}
//快速排序
void quickSort(int A[], int left, int right) {
if (left < right) { //当前区间的长度大于1
int pos = partition(A, left, right); //划分左右子区间
quickSort(A, left, pos - 1); //对左子区间递归进行快速排序
quickSort(A, pos + 1, right); //对右子区间递归进行快速排序
}
}
5.2 随机主元
int randPartition(int A[], int left, int right) {
//生成[left,right]内的随机数
int p = (int)(round(1.0 * rand() / RAND_MAX * (right - left) + left));
swap(A[p], A[left]); //交换A[p]和A[left]
int temp = A[left];
while (left < right) {
while (left < right && A[right] > temp) right--; //反复左移right
A[left] = A[right]; //将A[right]移到A[left]
while (left < right && A[left] < temp) left++; //反复右移left
A[right] = A[left]; //将A[left]移到A[right]
}
A[left] = temp; //把temp放到left和right相遇的地方
return left; //返回相遇的下标
}
void quickSort(int A[], int left, int right) {
if (left < right) { //当前区间的长度大于1
int pos = randPartition(A, left, right); //划分左右子区间
quickSort(A, left, pos - 1); //对左子区间递归进行快速排序
quickSort(A, pos + 1, right); //对右子区间递归进行快速排序
}
}