C++/数据结构——归并排序(递归和非递归)

归并排序

一.算法描述:

我们一般采用的是二路归并——折半归并,每次将数字的量缩小一倍;最后再将有序的数组两两合并。

二.实现——合并两个有序数组

1.意义:在这里,无论是递归还是非递归都是要进行有序数组合并这一步的;

2.步骤:

    1)将部分有序的数组分割成两个完全有序的数组——需要用到额外的空间来保存数组的值。

    2)合并

template <class T>
void merge(vector<T>& v, int left, int mid, int right) {
	vector<T> l(v.begin() + left, v.begin() + mid + 1);
	vector<T> r(v.begin() + mid + 1, v.begin() + right + 1);
	int i = 0, j = 0, k = left;
	while (i < l.size() && j < r.size()) {
		if (l[i] < r[j]) {
			v[k++] = l[i++];
		}
		else {
			v[k++] = r[j++];
		}
	}
	if (i >= l.size()) {
		while (j < r.size()) {
			v[k++] = r[j++];
		}
	}
	if (j >= r.size()) {
		while (i < l.size()) {
			v[k++] = l[i++];
		}
	}
}

三.递归版本:

1.利用函数调用栈的性质来实现归并

//递归
template <class T>
void _merge_sort(vector<T>& v, int left, int right) {
	if (left >= right) {
		return;
	}
	else {
		int mid = (left + right) / 2;
		_merge_sort(v, left, mid);
		_merge_sort(v, mid + 1, right);
		merge(v, left, mid, right);
	}
}

四.非递归版本

1.描述:

    需要解决的在于:如何将数组每次减半

方法:在这里我们设置一个变量sz用来控制每次归并的数据的量,该变量每次更新时翻倍更新即可

//非递归版本
template <class T>
void mergeSort(vector<T>& v, int size) {

	if (size < 2) {
		return;
	}
	int sz = 1;	//每次归并的组内的数字步幅
	while (sz <= size) {
		int begin = 0, mid = 0, end = 0;
		while (end < size - 1) {
			mid = begin + sz - 1;
			end = mid + sz;
			if (end >= size) {
				end = size - 1;
			}
			if (mid >= size) {
				mid = (begin + end) / 2;
			}
			merge(v, begin, mid, end);
			begin = end + 1;
		}
		sz *= 2;
	}
}

五.总结

注意:

    1.无论是递归还是非递归,我们需要注意的就是区间,在这里合并数组和递归版本的分割区间采用的都是闭区间。

    

发布了58 篇原创文章 · 获赞 43 · 访问量 4376

猜你喜欢

转载自blog.csdn.net/Wz_still_shuai/article/details/104520375