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

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

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

冒泡法:从第一个元素开始,依次比较相邻的两个元素,如果逆序则交换,第一趟比较结束后,序列中最大的元素将移动到序列末尾,即第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;
}

时间: 2024-08-29 11:53:35

【内部排序】 交换排序与选择排序详解的相关文章

C语言排序算法之简单交换法排序,直接选择排序,冒泡排序

C语言排序算法之简单交换法排序,直接选择排序,冒泡排序,最近考试要用到,网上也有很多例子,我觉得还是自己写的看得懂一些. 简单交换法排序 1 /*简单交换法排序 2 根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置 3 交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动 4 不稳定 5 */ 6 #include<windows.h> 7 #include<stdio.h> 8 void main(){ 9 int i,j,arr[10

插入排序 | 冒泡排序 | 希尔排序 | 堆排序 | 快速排序 | 选择排序 | 归并排序

以下是最近学习各种算法的代码实现: #include <stdlib.h> #include <stdio.h> #include <time.h> #include <limits.h> typedef int EleType; typedef int (*CompFunc)(void *,void *); int IntComp(void * a,void *b) { if(*(int *)a > *(int *)b) return 1; if(*

经典排序算法--简单选择排序

算法简介 简单选择排序是一种选择排序. 选择排序:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止. 白话理解 依然已排队为例,在排队时,有的老师可能会选择这样排序,先在一列中选出最矮的,放在第一位,然后选出第二矮的,放在第二位.队伍完成排序.而这就是选择排序的思想. 简单排序处理流程 (1)从待排序序列中,找到关键字最小的元素: (2)如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换: (3)从余下的 N - 1 个元素中,找出关键字最小

数据结构排序算法之选择排序

今天继续介绍一种排序算法:选择排序. 选择排序的基本思想就是从待排序列中选择出最小的,然后将被选出元素和序列的第一个元素互换位置(当前默认是升序排列),则互换完成后第一个元素就是整个序列的最小的元素,则一次选择排序结束.然后我们从剩下的子序列中选择出最小的,然后将该被选出来的元素和该子序列的第一个元素(即整个序列的第二个元素)互换位置,则当前整个序列的第二个元素就是当前序列中的次最小值,第二次选择排序结束.以此类推,直到该待排序列只剩下一个元素后,则整个序列有序. 具体过程如下图所示: 下面就不

排序算法之选择排序

一. 算法描述 选择排序:在一个长度为N的无序数组中,在第一趟遍历N个数据,找出其中最小的数值与第一个元素交换,第二趟遍历剩下的N-1个数据,找出其中最小的数值与第二个元素交换......第N-1趟遍历剩下的2个数据,找出其中最小的数值与第N-1个元素交换,至此选择排序完成. 二. 算法分析 平均时间复杂度:O(n2) 空间复杂度:O(1)  (用于交换和记录索引) 稳定性:不稳定 (比如序列[5, 5, 3]第一趟就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面) 三. 算法实现

算法学习之排序算法:选择排序

选择排序:每一趟在n-i+1(i=1,2,...,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录. 一.简单选择排序 一趟选择排序操作: 通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换之. 对L[1...n]中记录进行简单选择排序的算法为:令i从1至n-1,进行n-1趟选择操作.简单选择排序过程中,所需进行记录移动的操作次数较少,然而,无论记录的初始排列如何,所需关键字间的比较次数相同.因此,总的时间复杂度为O(n^2)

排序算法——直接选择排序

直接选择排序每一趟排序都会从未排序的序列中选择出最小的元素来,然后跟未排序序列的第一个元素交换.这样经过n-1趟排序后,每趟排序选择出的 最小元素便成了有序的序列. 算法实现如下: #include <stdio.h> #include <stdlib.h> void SelectSort(int A[],int n) { int i, j, index, temp; for(i = 0; i < n-1; i++) // 进行n-1趟排序 { index = i; // 辅

硬盘内部硬件结构和工作原理详解[zz]

一般硬盘正面贴有产品标签,主要包括厂家信息和产品信息,如商标.型号.序列号.生产日期.容量.参数和主从设置方法等.这些信息是正确使用硬盘的基本依据,下面将逐步介绍它们的含义. 硬盘主要由盘体.控制电路板和接口部件等组成,如图1-1所示.盘体是一个密封的腔体.硬盘的内部结构通常是指盘体的内部结构:控制电路板上主要有硬盘BIOS.硬盘缓存(即CACHE)和主控制芯片等单元,如图1-2所示:硬盘接口包括电源插座.数据接口和主.从跳线,如图1-3所示. 图1-1 硬盘的外观 图1-2 控制电路板 图1-

选择式排序法之选择排序法实现 -java版

计算算法时间复杂度比冒泡快一点 选择排序法核心思想是,第一次从R[0] ~R[n-1]中选择最小值然后与R[0]交换,第二次从R[1] ~R[n-1]中选取最小值与R[1]交换---第i次呢就是从R[i-1] ~R[n-1]中选取最小值,与R[i-1]元素交换:对于一个含有n个元素的数组,最多交换n-1次就得到了一个排序码从小到大的有序序列. package com.PengRong.A; import java.util.*; /** * * @author PengRong * */ pub

排序高级之选择排序_选择排序

选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理如下.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾.以此类推,直到所有元素均排序完毕. 选择排序的主要优点与数据移动有关.如果某个元素位于正确的最终位置上,则它不会被移动.选择排序每次交换一对元素,它们当中至少有一个将被移到其最终位置上,因此对n个元素的表进行排序总共进行至多n-1次交换.在所有的完全依靠交换去移动元素的排序方