1、归并排序
什么叫做归并排序?归并排序指的是利用"归并"技术来进行排序。归并是指将若干个已排序的子文件合并成一个有序的文件。如下图所示:
归并排序算法主要分成两部,一步是“分”,另一步是“并”,正如上图所表示的一样。分指的是从序列中进行二等分,以此分下去,直到序列长度为0或1为止。“分”对应的基本问题就是二分法;并指的是序列的合并。“并”对应的基本问题是指将两个顺序变化的序列合并成一个顺序变化的序列。
2、二分法的一个应用—二分查找
二分查找,顾名思义,指的就是在一个顺序序列中,找到该序列是否有相应的元素,如下图所示,在0~128中寻找元素77,寻找过程如下图所示:
(1)二分查找
//二分法查找数据 确定目标值是否在left_val~right_val之间
//找到返回1,没找到返回-1
int search(int left_val, int right_val, int target_val)
{
if(target_val < left_val)
return -1;
else if (target_val > right_val)
return -1;
else
{
int z = 0;
int mid = left_val + (right_val - left_val) / 2;
cout << mid << " ";
if (target_val < mid)
z = search(left_val,mid,target_val);
if (target_val > mid)
z = search(mid, right_val, target_val);
return z;
}
}
//二分法查找数组中的数据,找到返回1,没找到返回-1
int nums_search(int *nums,int left_index,int right_index,int target_val)
{
if (target_val < nums[left_index])
return -1;
else if (target_val > nums[right_index])
return -1;
else if (left_index > right_index)
return -1;
else
{
int mid = left_index + (right_index - left_index) / 2;
if (nums[mid] == target_val)
return 1;
if (target_val < nums[mid])
return nums_search(nums, left_index, mid-1, target_val);
if (target_val > nums[mid])
return nums_search(nums, mid+1, right_index, target_val);
}
}
(2) 两个顺序数组合并成同一个数组
//给两个顺序排列数组,合并为一个数组
int *merge_array(int *array1, int length1, int *array2, int length2)
{
int i = 0, j = 0, k = 0;
int sum_length = length1 + length2;
int *array3 = new int[sum_length];
for (;i<length1&j<length2; k++)
{
if (array1[i] < array2[j])
{
array3[k] = array1[i];
i++;
}
else
{
array3[k] = array2[j];
j++;
}
}
if (i != length1)
for (; i < length1; i++)
{
array3[k] = array1[i];
k++;
}
if (j != length2 )
for (; j < length2; j++)
{
array3[k] = array2[j];
k++;
}
return array3;
}
(3)归并排序
//归并排序
//并操作
void merge(int a[],int n,int left,int mid,int right)
{
int n1 = mid - left, n2 = right - mid;
int *L = new int[n1 + 1];
int *R = new int[n2 + 1];
for (int i = 0; i < n1; i++)
L[i] = a[left + i];
for (int i = 0; i < n2; i++)
R[i] = a[mid + i];
L[n1] = R[n2] = INF;
for (int i = 0, j = 0, k = left; k < right; k++)
{
if (L[i] <= R[j])
a[k] = L[i++];
else
a[k] = R[j++];
}
delete[]L;
delete[]R;
}
//分操作
void mergesort(int a[], int n, int left, int right)
{
if (left + 1<right)
{
int mid = (left + right) / 2;
mergesort(a, n, left, mid);
mergesort(a, n, mid, right);
merge(a, n, left, mid, right);
}
}
(4)最终版代码及测试
#include<stdio.h>
#include<iostream>
using namespace std;
//打印数组
void array_print(int *array, int length)
{
for (int i = 0; i < length; i++)
cout << array[i] << " ";
cout << endl;
}
//二分法查找数据 确定目标值是否在left_val~right_val之间
int search(int left_val, int right_val, int target_val)
{
if(target_val < left_val)
return -1;
else if (target_val > right_val)
return -1;
else
{
int z = 0;
int mid = left_val + (right_val - left_val) / 2;
cout << mid << " ";
if (target_val < mid)
z = search(left_val,mid,target_val);
if (target_val > mid)
z = search(mid, right_val, target_val);
return z;
}
}
//二分法查找数组中的数据
int nums_search(int *nums,int left_index,int right_index,int target_val)
{
if (target_val < nums[left_index])
return -1;
else if (target_val > nums[right_index])
return -1;
else if (left_index > right_index)
return -1;
else
{
int mid = left_index + (right_index - left_index) / 2;
if (nums[mid] == target_val)
return 1;
if (target_val < nums[mid])
return nums_search(nums, left_index, mid-1, target_val);
if (target_val > nums[mid])
return nums_search(nums, mid+1, right_index, target_val);
}
}
//给两个顺序排列数组,合并为一个数组
int *merge_array(int *array1, int length1, int *array2, int length2)
{
int i = 0, j = 0, k = 0;
int sum_length = length1 + length2;
int *array3 = new int[sum_length];
for (;i<length1&j<length2; k++)
{
if (array1[i] < array2[j])
{
array3[k] = array1[i];
i++;
}
else
{
array3[k] = array2[j];
j++;
}
}
if (i != length1)
for (; i < length1; i++)
{
array3[k] = array1[i];
k++;
}
if (j != length2 )
for (; j < length2; j++)
{
array3[k] = array2[j];
k++;
}
return array3;
}
//归并排序
//并操作
void merge(int a[],int n,int left,int mid,int right)
{
int n1 = mid - left, n2 = right - mid;
int *L = new int[n1 + 1];
int *R = new int[n2 + 1];
for (int i = 0; i < n1; i++)
L[i] = a[left + i];
for (int i = 0; i < n2; i++)
R[i] = a[mid + i];
L[n1] = R[n2] = INF;
for (int i = 0, j = 0, k = left; k < right; k++)
{
if (L[i] <= R[j])
a[k] = L[i++];
else
a[k] = R[j++];
}
delete[]L;
delete[]R;
}
//分操作
void mergesort(int a[], int n, int left, int right)
{
if (left + 1<right)
{
int mid = (left + right) / 2;
mergesort(a, n, left, mid);
mergesort(a, n, mid, right);
merge(a, n, left, mid, right);
}
}
//主函数
void main()
{
//二分法查找数据 确定目标值是否在left_val~right_val之间
//int value;
//while (true)
//{
// cin >> value;
// cout << search(1, 12, value) << endl;
//}
//二分法查找数组中的数据
//int nums[5] = { 1,3,5,6,9 };
//int value;
//while (true)
//{
// cin >> value;
// cout << nums_search(nums, 0, 4, value) << endl;
//}
//测试数组合并
//int a1[5] = { 1,3,5,7,9};
//int a2[7] = { 2,4,6,8,10,11,12};
//int length1 = sizeof(a1) / sizeof(int);
//int length2 = sizeof(a2) / sizeof(int);
//int *a3 = merge_array(a1, length1, a2, length2);
//array_print(a3, length1+length2);
//测试归并排序
//int a[11] = { 2,5,8,8,66,33,2,12,0,56,20 };
//array_print(a, 11);
//mergesort(a, 11, 0, 11);
//array_print(a, 11);
}
若有疑问和不足之处,可联系我本人邮箱13682749369@163.com