一、快速排序
快速排序基于分治思想,时间复杂度(nlogn)
快排的步骤:
- 确定分界点:q[left]、q[(left + right) / 2]、q[right] 三个其中一个都行
- 调整(划分)区间(快排的重点):把小于pivot的放在左区间,大于pivot的放在右区间
- 递归处理左右两个区间
算法思想:
在区间左右两端定义i和j两个指针,假设pivot为x,当i下标对应的元素小于x时i++,当i下标对应的元素不小于x时i不变,则开始移动j,当j下标对应的元素大于x时j--,当j下标对应的元素不大于x时j不变,交换i和j下标对应的元素,重复以上操作直到i和j相遇为止
//快速排序模板
void quick_sort(int q[], int left, int right){
if(left >= right)
return;
int i = left - 1, j = right + 1, pivot = q[left + right >> 1];
while(i < j){
do{
i++;
}while(q[i] < pivot);
do{
j--;
}while(q[j] > pivot);
if(i < j)
swap(q[i], q[j]);
}
quick_sort(q, left, j);
quick_sort(q, j + 1, right);
}
二、归并排序
归并排序基于分治思想,时间复杂度(nlogn)
归并步骤:
- 确定分界点:mid = left + (right - left) / 2
- 递归排序左右区间
- 归并(归并排序的重点):把两个有序的数组合并成一个有序的数组(合二为一)
算法思想:
归并简单来说其实就是比较两个数组,把两个数组中比较小的数插入到新的数组中
//归并排序模板
void merge_sort(int q[], int left, int right){
if(left >= right)
return;
int mid = left + (right - left) / 2; //(right + left) >> 1;
merge_sort(q, left, mid);
merge_sort(q, mid + 1, right);
int k = 0, i = left, j = mid + 1;
//两两比较
while(i <= mid && j <= right){
if(q[i] <= q[j])
temp[k++] = q[i++];
else
temp[k++] = q[j++];
}
//把两个数组剩余的元素插入到temp数组
while(i <= mid)
temp[k++] = q[i++];
while(j <= right)
temp[k++] = q[j++];
//将排序结果赋回给原数组
for(int i = left, j = 0; i <= right; i++, j++)
q[i] = temp[j];
}
三、二分查找
二分查找的本质是在某种性质下找到满足和不满足的边界
bool check(int x) {/* ... */} //检查x是否满足某种性质
// 区间[left, right] 被划分成[left, mid] 和 [mid + 1, right]时使用
int bsearch_1(int left, int right){
while(left < right){
int mid = left + right >> 1;
if(check(mid))
right = mid;
else
left = mid + 1;
}
return left;
}
// 区间[left, right] 被划分成[left, mid - 1] 和 [mid, right]时使用
int bsearch_1(int left, int right){
while(left < right){
int mid = left + right + 1 >> 1;
if(check(mid))
left = mid;
else
right = mid - 1;
}
return left;
}