数据结构Vector之选择排序、冒泡排序、归并排序

在前面介绍完Vector向量类的实现后,在此处简要介绍三个排序算法的实现,其中包括代码以及图示例。


1>下面首先介绍选择排序。选择排序是选定首端或者末端作为遍历开端,此处假定选定末端。在一次从后往前遍历的过程中,在指针指向元素的前方,选出其中最大的一个值,与指针指向的元素交换。每一次交换都保证最大值排在此指针上次元素的后面。具体代码如下所示。

template <typename T>
void Vector<T>::selectSort(Rank lo, Rank hi)	//选择排序
{
	while (lo < --hi)							//这里并没有将hi列出排序中
	{
		swap(_elem[max(lo, hi)], _elem[hi]);	//将hi与【lo,hi】中的最大值交换
	}
}

template<typename T>
Rank Vector<T>::max(Rank lo, Rank hi)			//选出范围最大值
{
	Rank mx = hi;								//记录一下范围末位元素	
	while (lo < hi--)
	{
		if (_elem[hi]>_elem[mx])				//一次遍历找出最大值
			mx = hi;
	}
	return mx;									//返回最大值的秩,即下标
}

只看代码没有感性的认识,下面附上一张选择排序的示例图。


主要步骤是选出指针指向元素前方的最大值与指针指向元素交换,在经过一轮的遍历以后,这个区间的元素就是从小到大排好序的了。


2> 下面介绍一下冒泡排序。冒泡排序的主要思想是:如果相邻两个元素局部无序,那么将两个元素交换,形成局部有序。在第一遍扫描的时候,将最大值置于最后一个位置。在第二遍扫描的时候,将仅次于最大值的值置于倒数第二个位置,以此类推,故名冒泡排序。具体代码如下所示。

template<typename T>
void Vector<T>::bubbleSort(Rank lo, Rank hi)	//冒泡排序
{
	while (!bubble(lo, hi--));
}
注:bubble方法返回的是bool值,这个值代表着这个向量是不是已经排好序。


下面贴出bubble方法的代码。

template<typename T>
bool Vector<T>::bubble(Rank lo, Rank hi)
{
	bool sorted = true;
	while (++lo < hi)
	{
		if (_elem[lo - 1]>_elem[lo])
		{
			sorted = fasle;
			swap(_elem[lo - 1], _elem[lo]);	//交换两个值
		}
	}

	return sorted;
}
注:此方法只是检测相邻两个元素的是不是有序。


下面贴出冒泡排序的示意图。


注:图示的解析已经比较清楚,故不再做进一步介绍。


3>下面介绍一下归并排序。归并排序,顾名思义也是将散的元素组合到一起,主要思想是:首先将元素较平均的分成两堆,然后递归的将这个两堆分别在分成两堆,在最后分到每组最多只剩下两个元素的时候,开始整合。整合主要实现是将两个组中的队首元素抽出来,比较两个值的大小,将小的值拿出来,放到第一位,以此类推,最后实现整个向量元素的排序。具体代码如下所示。

template<typename T>
void Vector<T>::mergeSort(Rank lo, Rank hi)
{
	if (hi - lo < 2)
		return;
	int mi = (lo + hi) >> 1;
	mergeSort(lo, mi);
	mergeSort(mi, hi);
	merge(lo, mi, hi);
}
注:此处使用递归将向量均分。


下面给出merge方法代码。

template<typename T>
void Vector<T>::merge(Rank lo, Rank mi, Rank hi)
{
	T* A = _elem + lo;								//将指针前移lo位,指向lo元素的内存空间
	int lb = mi - lo;								//记录前部分的元素数值
	t* B = new T[lb];								//创建新数组,存放前部分元素
	for (Rank i = 0; i < lb; B[i] = A[i++]);		//实现B[i]=A[i]
	int lc = hi - mi;								//记录后部分数组总数
	T* C = _elem + mi;								//指针前移mi位,指向mi元素的内存空间
	for (Rank i = 0, j = 0, k = 0; (j < lb) || (k < lc);)
	{
		if ((j < lb) && (!(k < lc) || (B[j] <= C[k])))
			A[i++] = B[j++];							//此处更改了内部数组,实现排序
		if ((k < lc) && (!(j < lb) || (C[k] < B[j])))
			A[i++] = C[k++];
	}

	delete[] B;
}
下面给出归并排序的示例图,稍微有点乱,后期再进行更改吧。




经过这么几次的画图与查询资料,自己收获了很多。在以后的学习生涯中,应该持着仔细的态度,认真钻研每一个问题,任何一个自己没有懂的小点,里面可能涉及到很多知识。尤其在指针这一块,以后该继续加强喽。


版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-10-23 00:25  会孵蛋的鱼  阅读(1025)  评论(0编辑  收藏  举报