数据结构与算法学习(2)
一.递归
二.归并排序
void Merge(vector<int>& arr, int left, int mid, int right) {
vector<int> tmp(right - left + 1, 0);
int p1 = left;
int p2 = mid + 1;
int i = 0;
while (p1 <= mid && p2 <= right)
{
tmp[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= mid)
{
tmp[i++] = arr[p1++];
}
while (p2 <= right)
{
tmp[i++] = arr[p2++];
}
for (int i = 0; i < tmp.size(); i++)
{
arr[left + i] = tmp[i];
}
}
void Sort04(vector<int>& arr, int left, int right) {
if (left >= right)return;
int mid = left + ((right - left) >> 1);
Sort04(arr, left, mid);
Sort04(arr, mid + 1, right);
Merge(arr, left, mid, right);
}
1.小和问题
int Merge01(vector<int>& arr, int left, int mid, int right) {
vector<int> tmp(right - left + 1, 0);
int p1 = left;
int p2 = mid + 1;
int i = 0;
int num = 0;
while (p1 <= mid && p2 <= right)
{
num += arr[p1] <= arr[p2] ? (right - p2 + 1) * arr[p1] : 0;
tmp[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= mid)
{
tmp[i++] = arr[p1++];
}
while (p2 <= right)
{
tmp[i++] = arr[p2++];
}
for (int i = 0; i < tmp.size(); i++)
{
arr[left + i] = tmp[i];
}
return num;
}
int Test05(vector<int>& arr, int left, int right) {
if (left >= right)return 0;
int mid = left + ((right - left) >> 1);
return Test05(arr, left, mid) + Test05(arr, mid + 1, right) + Merge01(arr, left, mid, right);
}
2.逆序对问题
int Merge01(vector<int>& arr, int left, int mid, int right) {
vector<int> tmp(right - left + 1, 0);
int p1 = left;
int p2 = mid + 1;
int i = 0;
int num = 0;
while (p1 <= mid && p2 <= right)
{
num += arr[p1] > arr[p2] ? (mid - p1 + 1) : 0;
tmp[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= mid)
{
tmp[i++] = arr[p1++];
}
while (p2 <= right)
{
tmp[i++] = arr[p2++];
}
for (int i = 0; i < tmp.size(); i++)
{
arr[left + i] = tmp[i];
}
return num;
}
int Test05(vector<int>& arr, int left, int right) {
if (left >= right)return 0;
int mid = left + ((right - left) >> 1);
return Test05(arr, left, mid) + Test05(arr, mid + 1, right) + Merge01(arr, left, mid, right);
}
三.快速排序
一般的快排
void Sort05(vector<int>& arr, int left, int right) {
if (left >= right)return;
int less = 0;
int high = right;
int base = arr[right];
while (less < high)
{
while (arr[less] <= base && less < high)
less++;
while (arr[high] >= base && less < high)
high--;
if (less < high)
Swap(arr, less, high);
}
arr[right] = arr[high];
arr[high] = base;
Sort05(arr, left, high - 1);
Sort05(arr, high + 1, right);
}
优化1.不取最后一个数,防止复杂度下降到n^2,而是随机抽取一个数放到结尾
优化2.每次排序将相同的数直接排完放到中间
vector<int> Test06(vector<int>& arr, int left, int right) {
int less = left - 1;
int high = right;
while (left < high)
{
if (arr[left] < arr[right])
Swap(arr, left++, ++less);
else if (arr[left] > arr[right])
Swap(arr, --high, left);
else
left++;
}
Swap(arr, right, high);
return{ less,high };
}
void Sort06(vector<int>& arr, int left, int right) {
if (left >= right)return;
vector<int> tmp = Test06(arr, left, right);
Sort06(arr, left, tmp[0]);
Sort06(arr, tmp[1], right);
}
1.小于等于指定数在左边大于指定数在右边
void Test08(vector<int>& arr, int num) {
int left = -1;
for (int i = 0; i < arr.size(); i++)
{
if (arr[i] <= num) {
Swap(arr, ++left, i);
}
}
}
2.荷兰国旗问题
void Test07(vector<int>& arr, int num) {
int less = -1;
int high = arr.size();
int left = 0;
while (left < high)
{
if (arr[left] < num)
Swap(arr, left++, ++less);
else if (arr[left] > num)
Swap(arr, --high, left);
else
left++;
}
}