本文用于记录个人算法竞赛学习,仅供参考
一.快速排序(升序为例)
思想:确定分界点x,将小于分界点的值放在分界点的左边,将大于分界定的值放在分界点的右边,再递归处理两边的左右区间。
步骤:
1.确定分界点:分界定的确定是随机的,一般取中间点(mid)和左右(L,R)边界点
2.调整区间:将小于分界点的值放在分界点的左边,将大于分界定的值放在分界点的右边(降序相反)
3.递归:递归处理左右两边,重复上述操作
调整区间的实现方式:
1.可以开辟两个空间来存放分界点的值,然后再拷贝回去,但这样会额外消耗空间
2.双指针法:L为左边界,R为右边界,用i 从L出发,用j 从R出发,i 向前遍历,直到遇到大于分界点x 的值并停下来,j 向后遍历,直到遇到小于x 的值并停下来,接着i 与j 指向的值交换,再继续重复上述操作直到i 与 j 相遇。
快排模板--O(N*logN)
void quick_sort(int q[], int l, int r)
{//只剩一个数,就不需要再操作了if (l >= r) return;//这里-1和+1是因为后面的do while操作int i = l - 1, j = r + 1;int x = q[(l + r) >> 1];while (i < j){do i++;while (q[i] < x);do j--;while (q[j] > x);//这里需要判断,因为有可能会出现i == jif (i < j)swap(q[i], q[j]);}//递归左右两边quick_sort(q, l, j);quick_sort(q, j + 1, r);
}
二.归并排序(升序为例)
思想:将两个有序数组合并成一个有序数组,那么归并排序整体就是先递归排序,再将有序数组合并成一个数组
步骤:
1.确定分界定:mid = (l + r) >> 1;
2.递归排序左边和右边
3.将两个有序的数组合并成一个数组--双指针遍历两个数组比较大小
归并模板--O(N*logN)
const int N = 100010;
int temp[N];
void merge_sort(int q[], int l, int r)
{if (l >= r) return;int mid = (l + r) >> 1;merge_sort(q, l, mid);merge_sort(q, mid + 1, r);//合并int index = 0, i = l, j = mid + 1;while (i <= mid && j <= r){if (q[i] < q[j]) temp[index++] = q[i++];else temp[index++] = q[j++];}while (i <= mid) temp[index++] = q[i++];while (j <= r) temp[index++] = q[j++];//拷贝回去for (i = l, index = 0; i <= r; i++,index++){q[i] = temp[index];}
}