排序

排序算法稳定性的简单形式化定义为:
如果Ai = Aj,排序前Ai在Aj之前,排序后Ai还在Aj之前,则称这种排序算法是稳定的。
通俗地讲就是保证排序前后两个相等的数的相对顺序不变
对于不稳定的排序算法,只要举出一个实例,即可说明它的不稳定性;
而对于稳定的排序算法,必须对算法进行分析从而得到稳定的特性。
需要注意的是,排序算法是否为稳定的是由具体算法决定的,不稳定的算法在某种条件下可以变为稳定的算法,
而稳定的算法在某种条件下也可以变为不稳定的算法。
例如,对于冒泡排序,原本是稳定的排序算法,如果将记录交换的条件改成A[i] >= A[i + 1],则两个相等的记录就会交换位置,
从而变成不稳定的排序算法。

插入排序

O(n^2)稳定排序

将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,
然后从第2个记录逐个进行插入,直至整个序列有序为止
设立第一个位置元素,每读入一个数立即插入到序列中,使每次插入有序。
核心思想:每插入一个元素使子序列有序

void insert_Sort(int *traget, int n)
{	//插入排序数组元素为n的目标数组traget
	int i, j, temp;
	for (i = 1; i < n; i++)
	{	//从第二个位置元素开始比较 
		j = i;
		temp = traget[i];//取出当前元素值 
		while (j > 0 && temp < traget[j - 1])
		{	//当前元素比前面元素小,前面元素向后移动直至比当前元素小 
			traget[j] = trager[j - 1];
			j--;
		}
		traget[j] = temp;//把当前元素放在适合的位置使有序。
	} 
}

选择排序

O(n^2)不稳定排序

在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。即找出最小的元素与当前元素互换位置。

void select_Sort(int *traget, int n)
{	//插入排序数组元素为n的目标数组traget 
	int i, j, k, temp;
	for (i = 0; i < n - 1; i++)
	{
		k = i;//记录当前坐标
		for (j = i + 1; j < n; j++)
		{	//找到剩下的最小元素的下标
			if (traget[j] < traget[k])
			{
				k = j;
			}
		}
		temp = traget[k];
		traget[k] = trager[i];
		traget[i] = temp;//当前元素与剩下元素最小的元素互换 
	}
} 

冒泡排序

O(n^2)稳定排序

在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,
较小的往上冒。
即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
如果有n个数,要比较n-1趟,第i趟,比较n-i次。

void bubble_Sort(int *traget, int n)
{	//冒泡排序数组元素为n的目标数组traget
	int i, j, temp;
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = 0; j < n - 1 - i; j++)
		{	//相邻两个元素比较之后交换
			if (a[j + 1] < a[j])
			{
				temp = a[i];
				a[i] = a[j];
				a[j] = temp;
			}
		}
	}
}

快速排序

O(nlogn)不稳定排序

基准+分区---------设立基准进行递归分区,分区排序。
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序n个元素要O(nlogn)次比较。在最坏状况下则需要O(n^2)次比较,但这种状况并不常见。事实上,**快速排序通常明显比其他O(nlogn)算法更快,**因为它的内部循环可以在大部分的架构上很有效率地被实现出来。快速排序使用分治策略(Divide and Conquer)来把一个序列分为两个子序列。
步骤为:

  1. 从序列中挑出一个元素,作为"基准"(pivot).
  2. 把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区(partition)操作。
  3. 对每个分区递归地进行步骤1~2,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了。
// 分类 ------------ 内部比较排序
// 数据结构 --------- 数组
// 最差时间复杂度 ---- 每次选取的基准都是最大(或最小)的元素,导致每次只划分出了一个分区,
需要进行n-1次划分才能结束递归,时间复杂度为O(n^2)
// 最优时间复杂度 ---- 每次选取的基准都是中位数,这样每次都均匀的划分出两个分区,只需要logn次划分就能结束递归,
时间复杂度为O(nlogn)
// 平均时间复杂度 ---- O(nlogn)
// 所需辅助空间 ------ 主要是递归造成的栈空间的使用(用来保存left和right等局部变量),取决于递归树的深度,
一般为O(logn),最差为O(n)       
// 稳定性 ---------- 不稳定

void swap(int *traget, int i, int j)
{	//交换数组元素 
	int temp = traget[i];
	traget[i] = traget[j];
	traget[j] = temp;
}
int partition(int *traget, int low, int high)
{	//划分区间,把比基准小的放在基准左边,把比基准大的放在基准右边 
	int pivot = traget[high]; // 这里每次都选择最后一个元素作为基准
	int tail = low - 1;//子数组首元素下标的前驱 
	int i;
	for (i = low; i < high; i++)
	{	//不取到最后一个元素,最后一个元素作为基准 
		if (traget[i] <= pivot)
		{	//比基准小交换 
			swap(traget, i, ++tail); 
		}
	}
	swap(traget, high, tail + 1);
	//基准移动到区间中间位置,基准后的子数组元素比基准大 
	//该操作很有可能把后面元素的稳定性打乱,所以快速排序是不稳定的排序算 
	return tail + 1;
}
void quick_Sort(int *traget, int low, int high)
{
	if (low >= high)
	{	//区间长度小于0不用排序了 
		return ;
	}
	int pivot_Index = partition(traget, low, high);//分区的基准索引 
	quick_Sort(traget, low, pivot_Index - 1);//继续划分基准左边的子数组 
	quick_Sort(traget, pivot_Index + 1, high);//继续划分基准右边的子数组 
} 

快速排序是不稳定的排序算法,不稳定发生在基准元素与A[tail+1]交换的时刻。
比如序列:{ 1, 3, 4, 2, 8, 9, 8, 7, 5 },基准元素是5,一次划分操作后5要和第一个8进行交换,从而改变了两个元素8的相对次序。
对于基础类型,相同值是无差别的,排序前后相同值的相对位置并不重要,所以选择更为高效的快速排序,尽管它是不稳定的排序算法;而对于非基础类型,排序前后相等实例的相对位置不宜改变,所以选择稳定的归并排序。

归并排序

归并排序是创建在归并操作上的一种有效的排序算法,效率为O(nlogn),1945年由冯·诺伊曼首次提出。
归并排序的实现分为递归实现与非递归(迭代)实现。递归实现的归并排序是算法设计中分治策略的典型应用,
我们将一个大问题分割成小问题分别解决,然后用所有小问题的答案来解决整个大问题。
非递归(迭代)实现的归并排序首先进行是两两归并,然后四四归并,然后是八八归并,一直下去直到归并了整个数组。
归并排序算法主要依赖归并(Merge)操作。归并操作指的是将两个已经排序的序列合并成一个序列的操作,归并操作步骤如下:
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
设定两个指针,最初位置分别为两个已经排序序列的起始位置
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针到达序列尾

将另一序列剩下的所有元素直接复制到合并序列尾归并排(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

逆序对:序列(a,b)如果a>b,那么称a,b为一组逆序对。在只能交换相邻元素的位置的情况下,使序列有序的最小交换次数为逆序对的组数。逆序对是归并排序的附属产物。
POJ(逆序对题目)

// 分类 -------------- 内部比较排序
// 数据结构 ---------- 数组
// 最差时间复杂度 ---- O(nlogn)
// 最优时间复杂度 ---- O(nlogn)
// 平均时间复杂度 ---- O(nlogn)
// 所需辅助空间 ------ O(n)
// 稳定性 ------------ 稳定
void merge(int *traget, int low, int mid, int high)
{	//归并数组
	int i = low;
	int j = mid + 1;
	int k = 0;
	int* temp = new int[high - low + 1];//临时数组
	//C语言实现 : temp = (int*)malloc(sizeof(int) * (high - low + 1);
	while (i <= mid && j <= high)
	{
		if (traget[i] <= traget[j])
		{	//两个子数组中较小的元素放入数组
			//带等号保证归并排序的稳定性
			temp[k++] = traget[i++];
		}
		else
		{
			temp[k++] = traget[j++];
			count += mid - i + 1;//逆序对数
		}
	}
	//一个数组元素全部放入之后,将另一个数组直接复制过去
	while (i <= mid)
	{	
		temp[k++] = traget[i++];
	}
	while (j <= high)
	{
		temp[k++] = traget[j++];
	}
	for (i = 0; i < k; i++)
	{
		traget[low++] = temp[i];
	}
	delete[]temp;
} 
void mergeSort(int *traget, int low, int high)
{
	if (low == high)
	{	//子数组长度为1不用排序
		return;
	}
	int mid = (low + high) >> 1;
	mergeSort(traget, low, mid);
	mergeSort(traget, mid + 1, high);
	merge(traget, low, mid, high);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值