归并排序来袭

归并排序的基本思想是将两个或两个以上的有序表组合成一个新的有序表。来张丑图:

来上代码:

//归并排序递归
void Merge(int *arr, int start, int mid, int end)
{
	assert(NULL != arr);
	int low = start;
	int high = mid + 1;
	int *brr = (int *)malloc(sizeof(int)*(end - start + 1));
	int i = 0;
	while (low <= mid && high <= end)
	{
		if (arr[low] < arr[high])
		{
			brr[i++] = arr[low++];
		}
		else
		{
			brr[i++] = arr[high++];
		}
	}
	while (low <= mid)
	{
		brr[i++] = arr[low++];
	}
	while (high <= end)
	{
		brr[i++] = arr[high++];
	}

	for (int k = 0; k <i ; k++)    ///////注意
	{
		arr[start + k] = brr[k];
	}
	free(brr);
}

void Mesort(int *arr, int start, int end)
{
	assert(NULL != arr);
	if (start < end)
	{
		int mid = (start + end) / 2;  
		Mesort(arr, start, mid);   //先分后合
		Mesort(arr, mid + 1, end);
		Merge(arr, start, mid, end);
	}
}

是不是感觉递归那块有点迷糊,来看下面这这张丑图:

 是不是感觉清晰点了,讲真,不懂多画图,没毛病!!

以上是归并排序的递归实现,那么如何将递归变为非递归呢?发现递归主要是一层一层进去,等到合并的两个有序表为1的时候才开始合并,那么我们是不是可以直接控制这两个有序表的大小,没错,当然可以,看代码:

//归并排序非递归
void meger(int *arr, int len, int gap)
{
	int *brr = (int *)malloc(sizeof(int)* len);
	assert(brr != NULL);

	int i = 0;
    //初始化要合并的区间,2路归并
	int L1 = 0;
	int H1 = L1 + gap - 1;

	int L2 = H1 + 1;
	int H2 = L2 + gap - 1 <= len - 1 ? L2 + gap - 1 : len - 1;

	while (L2 <= len - 1)
	{
		while (L1 <= H1 && L2 <= H2)
		{
			if (arr[L1] <= arr[L2])
			{
				brr[i++] = arr[L1++];
			}
			else
			{
				brr[i++] = arr[L2++];
			}
		}

		while (L1 <= H1)
		{
			brr[i++] = arr[L1++];
		}
		while (L2 <= H2)
		{
			brr[i++] = arr[L2++];
		}
        //让区间后移,继续进行合并
		L1 = H2 + 1;
		H1 = L1 + gap - 1;
		L2 = H1 + 1;
		H2 = L2 + gap - 1 < len - 1 ? L2 + gap - 1 : len - 1;
	}

	while (L1<len)
	{
		brr[i++] = arr[L1++];
	}

	for (int i = 0; i<len; i++)
	{
		arr[i] = brr[i];  //最后将值再赋给原来的数组
	}
	free(brr);
}
void MegerSort(int *arr, int len)
{
	//子序列长度不断变化
	for (int i = 1; i<len; i = i * 2)
	{
		meger(arr, len, i);
	}
}

程序中用for循环直接控制了要归并的序列的区间大小,即1,2,4,8,16

是不是感觉也非常的清晰,代码中的L1,H1,L2,H2是自己定义的要归并的序列的区间值。

来说下归并排序的复杂度:

递归

一趟归并需要将待排序序列中的所有记录扫描一遍,耗费O(n),整个归并排序需要进行(log2N,以2为底N的对数向上取整)次,所以总的时间复杂度是O(n*logn)。  

空间复杂度是O(n+logn)包括栈空间。

非递归:

避免了栈空间的消耗,避免递归也减少了时间时间开销。建立归并使用非递归。

归并排序是两两比较,不存在跳跃,所以是稳定的一种排序。

 

源码链接: https://pan.quark.cn/s/a4b39357ea24 银行信贷业务作为银行业务的关键构成部分,涵盖了银行向客户提供的各类融资服务,例如贷款、担保以及信用证等。此类业务致力于协助企业与个人解决资金需求问题,进而推动经济活动的开展。银行通过信贷业务获取利息收入,同时需承担相应风险,以保障资金的稳定与流转。 **信贷定义** 信贷意味着银行运用自身资本及信誉为客户提供资金支持,而客户则需以支付利息、费用并偿还本金为前提条件。这种业务模式不仅包含直接贷款,还包括为客户的债务承担提供担保。依照会计准则,信贷业务可分为表内业务与表外业务,前者对银行的资产负债表产生直接影响,后者则不直接关联。 **信贷业务划分标准** 1. **依据会计核算归属**:表内信贷(如贷款、贴现)和表外信贷(如承兑、保证)。 2. **根据期限划分**:短期(不超过1年)、中期(1至5年)与长期(超过5年)。 3. **按照担保方式分类**:信用信贷(无担保)和担保信贷(保证、抵押、质押)。 4. **按照币种区分**:本币信贷与外币信贷。 5. **按照性质和用途区分**:固定资产贷款、流动资金贷款、循环额度贷款、消费贷款等。 6. **按照贷款组织形式区分**:普通贷款、联合贷款和银团贷款。 7. **按照资金来源区分**:信贷资金贷款、委托贷款和境外筹资转贷款。 8. **按照授信对象区分**:公司类信贷与个人类信贷。 **信贷业务产品** 1. **流动资金贷款**:用于企业日常运营周转或临时性资金需求。 2. **固定资产贷款**:用于投资固定资产项目。 3. **房地产开发贷款**:用于土地开发及房屋建设所需资金。 4. **循环额度贷款**:满足企业...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值