常用排序算法-归并排序

一:主要思想

   将若干个有序序列逐步归并,最终合成一个有序队列

二:问题

 1:怎样构造初始有序队列

 2:两个相邻的队列如何合成一个有序队列

 3:怎样完成一趟和合并(二种我们只完成了前面相邻的)

 4:完成归并结束的标志是什么

三:问题的解决

1:初始长度为1的有序序列

2:相邻数组中按照大小依次放到暂存数组

/**
	 * 1:我们将代排序列看成长度为1的n个有序序列 2:两个相邻的如何合并成一个有序序列 s:第一个数列第一个位置 m:第一个数列最后一个位置
	 * t:第二个数列某位置 k:合并之后队列的首位置
	 * 
	 * 我们传的是原数组,暂存数组,有序队列第一位置,最后一个位置,有序队列第二个末位置
	 */
	public void merge(int r[], int r1[], int s, int m, int t) {
		int i, j, k;
		i = s;
		j = m + 1;
		k = s;
		while (i < m && j < t)
		{
			if (r[i] < r[j])
				r1[k++] = r[k++];
			else
				r1[k++] = r[j++];
		}
		// 第一个没处理完或者第二个,没处理完
		if (i < m) {
			while (i < m)
				r1[k++] = r[i];
		} else {
			// 第二个数组,没处理完
			while (j < t)
				r1[k++] = r[j++];
		}
	}

三:怎么样把剩下的一趟合并

3.1:我们分三种情况

1:合并的全是前面的

2:合并到末尾

    2.1:剩一个长度小于h的和长度为h的

    2.2:只剩下一个长度为h的

public void MergePass(int r[], int r1[], int n, int h) {
		int i = 1;
		/**
		 * 1:合并两个长度都为h; 2:合并一个H,另一个小于h(末尾情况) 3:合并自剩下一个h,我们把它挂在合并之后的数组中
		 */
		// 1:合并长度都为h的有序序列
		while (i < n - 2 * h + 1) {
			// 看1是否减掉,我们看i是否包含里面
			merge(r, r1, i, i + h - 1, i + 2 * h - 1);
			// i的值后移2h未
			i += 2 * h;
		}
		// 2:合并到最后后剩一个长度小于h,和一个长度为h的数组
		if (i < n - h + 1) {
			merge(r, r1, i, i + h - 1, n);
		} else {
			for (int k = i; k < n; k++) {
				r1[k] = r[k];
			}
		}

	}

四: 结束标志

初始长度为1,我们判断最后队列长度是否为n,作为结束标志

	/**
    *判断结束 
    */
	public void MergeSort(int r[],int r1[],int n) {
		int h=1;
		while(h<n)
		{
			MergePass(r, r1, n, h);//排序好的数组我们放到暂存数组中了
			h=2*h;
			MergePass(r1,r ,n, h);//我们把暂存数组中的倒到我们原数组中和
	        h=2*h;
		}
	}
	




猜你喜欢

转载自blog.csdn.net/qq_37154446/article/details/79970006