【内部排序】 交换排序与选择排序详解


交换排序:通过依次交换逆序的元素使其有序化的过程。


介绍两种交换排序: 冒泡排序,快速排序


冒泡法:从第一个元素开始,依次比较相邻的两个元素,如果逆序则交换,第一趟比较结束后,序列中最大的元素将移动到序列末尾,即第n个位置,第二趟将次大元素移动到n-1位置…… 多趟比较后,会形成有序序列,排序方法类似气泡慢慢向上浮动,因此成为冒泡法。



快速排序: 对冒泡的改进,将序列中的关键字和指定元素(枢轴)比较,将序列以枢轴划分,保证枢轴大于其左边所有数,小于其右边所有数

枢轴的选取很关键,避免快排在局部有序数列中退化,再次使用的三者取中法)

按照以上方法,对上次划分的子序列进行递归划分,知道每个子序列只剩下一个元素不能划分为止,此时序列有序。


代码实现:


#include<iostream>
#define SIZE 21  
typedef int Sqlist[SIZE];

using namespace std;

void swap(int &a, int &b)
{
	a = a^b;
	b = a^b;
	a = a^b;
}

//==================================BubbleSort()==================================
/// @brief <对函数进行概括说明>	冒泡排序 
/// 
/// <对函数进行详细说明>	内部排序,稳定排序,交换排序 时间复杂度:平均 O(n),最坏O(n^2)
///
/// @param [in, out] sq <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> 数组
/// @param [in, out] n <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择>  数组大小
///
/// @return <返回值说明,可以配合使用DocGenList或DocGenTable>	无返回值
///
/// @remark <函数特别说明>	使用引用
///
/// @code
///      <在此添加示例代码>
/// @endcode
void BubbleSort(Sqlist &sq, int n)
{
	cout << "冒泡排序:" << endl;
	for (int i = 0; i < n - 1; ++i)
	{
		for (int j = 0; j < n - i - 1; ++j)
		{
			if (sq[j] > sq[j + 1])
			{
				swap(sq[j],sq[j+1]);
			}
		}
	}
}
/

//================================PivotkeySelect()================================
/// @brief <对函数进行概括说明> 枢轴选取
///
/// <对函数进行详细说明>		三者取中  
///
//================================================================================
int PivotkeySelect(Sqlist &sq, int low, int high)
{
	int mid = low + ((high - low) >> 1);//计算数组中间的元素的下标  

	//使用三数取中法选择枢轴  
	if (sq[mid] > sq[high])//目标: sq[mid] <= sq[high]  
	{
		swap(sq[mid], sq[high]);
	}
	if (sq[low] > sq[high])//目标: sq[low] <= sq[high]  
	{
		swap(sq[low], sq[high]);
	}
	if (sq[mid] > sq[low]) //目标: sq[low] >= sq[mid]  
	{
		swap(sq[mid], sq[low]);
	}
	//此时,sq[mid] <= sq[low] <= sq[high]  
	return sq[low];
	//low的位置上保存这三个位置中间的值  
	//分割时可以直接使用low位置的元素作为枢轴,而不用改变分割函数了
}

//==================================Partition()=================================
/// @brief <对函数进行概括说明> 划分
///
/// <对函数进行详细说明> 用枢轴将数组划分
///
/// @sa <可以参考的类或函数,用空格分隔,函数名称后必须加()> PivotkeySelect()
//================================================================================
int Partition(Sqlist &sq, int low, int high)
{
	int key = PivotkeySelect(sq,low,high);					//辅助空间
	
	while (low < high)
	{
		while (low < high && sq[high] >= key)
		{
			high--;
		}
		sq[low] = sq[high];

		while (low < high && sq[low] <= key)
		{
			low++;
		}
		sq[high] = sq[low];
	}
	sq[low] = key;
	return low;
}

//==================================QuickSort()=================================
/// @brief <对函数进行概括说明> 快速排序	对冒泡的改进 不稳定
///
/// <对函数进行详细说明>	将关键字与指定元素比较 递归 时间复杂度:平均O(nlog2^n) 最坏O(n^2)
///
/// @param [in, out] sq <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> 数组
/// @param [in, out] low <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> 最小下标
/// @param [in, out] high <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> 最大下标
///
/// @return <返回值说明,可以配合使用DocGenList或DocGenTable>  返回low
///
/// @remark <函数特别说明>
///
/// @code
///      <在此添加示例代码>
/// @endcode
///
/// @sa <可以参考的类或函数,用空格分隔,函数名称后必须加()> Partition() PivotkeySelect()
//================================================================================
void QuickSort(Sqlist &sq, int low, int high)
{
	if (low < high)
	{
		int prvitloc = Partition(sq, low, high);     //将数组一分为二  
		QuickSort(sq, low, prvitloc - 1);              //左半部分排序  
		QuickSort(sq, prvitloc + 1, high);
	}
}

选择排序:


对于n个元素的序列,第一趟经n-1此比较,选出最小的放在第一个位置,第二趟从n-1个元素中,经过n-2次比较,选出最小的放在第二个位置……直到没有待比较的元素。


代码实现:

//====================================MinKey()====================================
/// @brief <对函数进行概括说明> 最小值选取
///
/// <对函数进行详细说明> 从key位置开始,找出大小为n数组中的最小值,并返回下标
///
/// @param [in, out] sq <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择>
/// @param [in, out] n <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择>
/// @param [in, out] key <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择>
///

//================================================================================
int MinKey(Sqlist &sq, int n, int key)
{
	int k = key + 1;
	for (; k < n; ++k)
	{
		if (sq[k] < sq[key])                         //若小于则记录下标  
		{
			key = k;
		}
	}
	return key;
}


//==================================SelectSort()==================================
/// @brief <对函数进行概括说明> 简单选择排序
///
/// <对函数进行详细说明> n个元素,第一次n-1次比较,选出n个中最小元素,放在序列最前面
///
/// @param [in, out] sq <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择>
/// @param [in, out] n <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择>
///
/// @return <返回值说明,可以配合使用DocGenList或DocGenTable> 
///
/// @remark <函数特别说明>
///
/// @code
///      <在此添加示例代码>
/// @endcode
///
/// @sa <可以参考的类或函数,用空格分隔,函数名称后必须加()> MinKey() swap()
//================================================================================
void SelectSort(Sqlist &sq, int n)
{
	for (int i = 0; i < n - 1; ++i)
	{
		int j = MinKey(sq, n, i);
		if (i != j)
			swap(sq[i],sq[j]);
	}
}

测试程序:

void main(void)
{
	Sqlist sq = { 49, 38, 65, 97, 76, 13, 27, 49 };
	Sqlist sq2 = { 49, 38, 65, 97, 76, 13, 27, 49 };
	Sqlist sq3 = { 49, 38, 65, 97, 76, 13, 27, 49 };
	cout << "原数组为:" << endl;
	
	for (int i = 0; i < 8; ++i)
	{
		cout << sq[i]<<" ";
	}
	cout << endl;

	BubbleSort(sq,8);

	for (int i = 0; i < 8; ++i)
	{
		cout << sq[i] << " ";
	}
	cout << endl;
/
	cout << "原数组为:" << endl;

	for (int i = 0; i < 8; ++i)
	{
		cout << sq2[i] << " ";
	}
	cout << endl;

	QuickSort(sq2, 0, 7);
	cout << "快速排序:" << endl;
	for (int i = 0; i < 8; ++i)
	{
		cout << sq2[i] << " ";
	}
	cout << endl;
	//
	cout << "原数组为:" << endl;

	for (int i = 0; i < 8; ++i)
	{
		cout << sq3[i] << " ";
	}
	cout << endl;

	SelectSort(sq3, 8);
	cout << "交换排序:" << endl;
	for (int i = 0; i < 8; ++i)
	{
		cout << sq3[i] << " ";
	}
	cout << endl;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值