归并排序及二分法

 

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

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值