浅析java归并排序的递归算法和迭代算法

1.递归算法的实现

递归算法相对来讲更好理解些,采用分治法进行实现,在拆分的元素个数小于三个的时候进行排序。这里first,last和mid都为数组元素的下标值。

private void mergeSort1(int[] src, int temp[], int first, int last) {
		if (last - first < 3) {// 拆分的元素个数小于等于3的时候进行排序
			sort(src, first, last);
			return;
		}

		int mid = (first + last) / 2;
		mergeSort1(src, temp, first, mid);
		mergeSort1(src, temp, mid + 1, last);


		int i = first;// 二分归并第一组元素的头指针
		int j = mid + 1;// 二分归并第二组元素的头指针
		int k = first;// 临时数组的头指针


		while (i <= mid && j <= last) {
			temp[k++] = src[i] < src[j] ? src[i++] : src[j++];
		}
		while (i > mid && j <= last) {
			</span>temp[k++] = src[j++];
		}
		while (j > last && i <= mid) {
			temp[k++] = src[i++];
		}


		arrayCopy(src, temp, first, last);


	}


	// 将临时数组的数据拷贝到原数组当中temp->src
	private void arrayCopy(int[] to, int[] from, int first, int last) {
		for (int i = first; i <= last; ++i) {
			to[i] = from[i];
		}
	}


	private void arrayCopy(int[] src, int[] temp) {
		arrayCopy(src, temp, 0, src.length - 1);
	}


	private void sort(int[] src, int first, int last) {
		// 采用冒泡排序的方式对小于等于3个的拆分过的数组进行排序
		int temp = 0;
		for (int i = first; i < last; ++i) {
			for (int j = first; j < last - i + first; ++j) {
				if (src[j] > src[j + 1]) {
					</span>temp = src[j];
					</span>src[j] = src[j + 1];
					</span>src[j + 1] = temp;
				}
			}
		}
	}


2.归并排序的迭代算法

归并排序的算法逻辑比较不容易理清,请大家自己代入几个数试一下很快就会明白。


private void mergeSort2(int[] src, int[] temp) {
		
		//设置最开始分隔元素的距离为2
		
//		如果我们要排序的数组为5,4,3,2,1  那么第一次就应该对间隔为2的元素进行先简单排序再归并
//		排序后数组为4,5   2,3    1
//		然后此时对4,5   2,3  进行归并,1自然落下
//		而后数组变为2,3,4,5  然后space进行加倍,重复步骤,此时space不为2,所以不再进行排序,直接
//		进行归并
		
		int space = 2;
		// 下次是否是归并到原数组中的判断。  最开始的归并是从src到temp数组中进行的
		boolean toSrc = false;
		int len = src.length;
		
		if(len == 2){
			int temp1 = 0;
			if(src[0]>src[1]){
				temp1 = src[0];
				src[0] = src[1];
				src[1] = temp1;
			}
		}
		int first = 0, last = 0, mid = 0;
		while (space < len) {
			for (int i = 0; i < len; i = last + 1) {
				first = i;
				mid = first + space - 1;
				last = first + space * 2 - 1;
				//在最末尾的元素大于数组最后一个元素的下标值时,将last设置为最后元素的下标值
				if (last >= len - 1)
					last = len - 1;
				// 在mid<=last的时候 我们认为数组中最后剩余的元素可以进行归并而不是直接落入下次归并中
				if (mid <= last) {
					if (space == 2) {
						compareForSwap(src, first, mid, last);
					}
					if (!toSrc) {
						//向temp中进行归并
						merge(src, temp, first, mid, last);
					} else {
						//向src中进行归并
						merge(temp, src, first, mid, last);
					}
				}else{
					if (!toSrc) {
						//向temp中进行拷贝剩余元素
						arrayCopy(temp, src, first, last);
					} else {
						//向src中进行拷贝剩余元素
						arrayCopy(src, temp, first, last);
					}
					
				}

			}
			// 代表下一步该归并到那个数组中
			toSrc = !toSrc;
			
			
			space *= 2;
		}
		// 如果下一步该要归并到src中,代表现在已经正确归并的值留在了temp中 我们需要将他们复制到src中
		if (toSrc) {
			arrayCopy(src, temp);
		}

	}

	//实现元素之间的比较判断以及交换
	private void compareForSwap(int[] src, int first, int mid, int last) {
		int temp = 0;
		if (src[first] > src[mid]) {
			temp = src[first];
			src[first] = src[mid];
			src[mid] = temp;
		}
		//这里用if判断使当最后的元素不足时不进行交换
		if (mid + 1 < last) {
			if (src[mid + 1] > src[last]) {
				temp = src[mid + 1];
				src[mid + 1] = src[last];
				src[last] = temp;
			}
		}
	}

	private void merge(int[] from, int[] to, int first, int mid, int last) {
		int i = first;// 二分归并第一组元素的头指针
		int j = mid + 1;// 二分归并第二组元素的头指针
		int k = first;// to数组的头指针

		while (i <= mid && j <= last) {
			to[k++] = from[i] < from[j] ? from[i++] : from[j++];
		}
		while (i > mid && j <= last) {
			to[k++] = from[j++];
		}
		while (j > last && i <= mid) {
			to[k++] = from[i++];
		}
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值