归并排序mergeSort以及小和问题

时光怂恿深爱的人放手 提交于 2020-01-26 03:23:49

归并排序
时间复杂度O(N*logN),额外空间复杂度O(N),实现可以做到稳定性

#include <cstdio>
#include <cstdlib>
void merge(int A[], int L, int mid, int R)//两个数组的合并过程,其中要注意的是要合并的两个数组分别一定是有序的
{
	int i = L, j = mid + 1, k = 0;
	int *help = (int*)malloc(sizeof(int)*(R - L + 1));//辅助数组
	while (i <= mid&&j <= R)
	{
		if (A[i] < A[j]) //那边数组数值小放入辅助数组help当中
		{
			help[k++] = A[i++];
		}
		else
		{
			help[k++] = A[j++];
		}
	}
	while (i <= mid)//其余两个while只会实现一个,那个数组没有放入help数组当中,循环放入
	{
		help[k++] = A[i++];
	}
	while (j <= R)
	{
		help[k++] = A[j++];
	}
	for (int i = 0; i < k; i++)//最后将辅助数组help当中的数值放入到当前A[]数组的当前排序区域
	{
		A[L + i] = help[i];
	}
}
void sortprosess(int A[], int L, int R)
{
	if (L == R)//递归边界   如果左边等于右边直接返回
	{
		return;
	}
	int mid = L + (R - L) / 2;
	sortprosess(A, L, mid);//递归的过程就是不断的二分
	sortprosess(A, mid + 1, R);
	merge(A, L, mid, R);
}
void mergeSort(int A[], int n)
{
	if (n == 0 || n == 1)
	{
		return;
	}
	else
	{
		sortprosess(A, 0, n - 1);
	}
}


int main()
{
	int A[] = { 32, 34, 65, 21, 23, 22, 11, 9, 8, 6, 4, 3, 2 };
	for (int i = 0; i < 13; i++)
	{
		printf("%d ", A[i]);
	}
	printf("\n");
	mergeSort(A, 13);
	for (int i = 0; i < 13; i++)
	{
		printf("%d ", A[i]);
	}
	printf("\n");
	return 0;
}

小和问题:
在一个数组中, 每一个数左边比当前数小的数累加起来, 叫做这个数组的小和。 求一个数组
的小和。
例子:

{1,3,4,2,5}

1左边比1小的数,没有

3左边比3小的数,1

4左边比4小的数,1,3

2左边比2小的数,1

5左边比5小的数,1,3,4,2
因此小和为1+1+3+1+1+3+4+2=16

还是需要强调的是merge合并过程中合并的两个数组分别是有序的!!因此在merge过程中只要左边数组有数值比右边小,右数组比较的该数值以及该数值之后的数值一定都大于左边当前比较的数值 

//merge中的第一个循环
while (i <= mid&&j <= R)
	{
		if (A[i] < A[j])//根据归并排序性质,合并过程中的两个数组一定是有序的;
                        //那么只要A[i]<A[j]则A[j]~A[R]必然大于A[i],即当前位置的小和为
                        //A[i]*(R-j+1); 
		{
			sum += A[i] * (R - j + 1);//小和数
			help[k++] = A[i++];
		}

只要设置一个全局变量记录所有小和的和即可

上边代码的小和

{ 32, 34, 65, 21, 23, 22, 11, 9, 8, 6, 4, 3, 2 }

32左边比32小的数, 没有;
34左边比34小的数, 32;
65左边比65小的数, 32、 34;
23左边比23小的数, 21;
22左边比22小的数,21;    因此小和为  32+32+34+21+21=140 

#include <cstdio>
#include <cstdlib>
int sum = 0;//----------------设置全局变量记录所有的小和
void merge(int A[], int L, int mid, int R)
{
	int i = L, j = mid + 1, k = 0;
	int *help = (int*)malloc(sizeof(int)*(R - L + 1));//辅助数组
	while (i <= mid&&j <= R)
	{
		if (A[i] < A[j])
		{
			sum += A[i] * (R - j + 1);//记录当前合并数组过程中的小和数
			help[k++] = A[i++];
		}
		else
		{
			help[k++] = A[j++];
		}
	}
	while (i <= mid)
	{
		help[k++] = A[i++];
	}
	while (j <= R)
	{
		help[k++] = A[j++];
	}
	for (int i = 0; i < k; i++)
	{
		A[L + i] = help[i];
	}
}
void sortprosess(int A[], int L, int R)
{
	if (L == R)
	{
		return;
	}
	int mid = L + (R - L) / 2;
	sortprosess(A, L, mid);
	sortprosess(A, mid + 1, R);
	merge(A, L, mid, R);
}
void mergeSort(int A[], int n)
{
	if (n == 0 || n == 1)
	{
		return;
	}
	else
	{
		sortprosess(A, 0, n - 1);
	}
}

int main()
{
	int A[] = { 1, 3, 4, 2, 5 };
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", A[i]);
	}
	printf("\n");
	mergeSort(A, 5);
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", A[i]);
	}
	printf("\n");
	printf("%d\n", sum);//输出小和
	return 0;
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!