IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构学习(列表:五(有序列表的排序算法)) -> 正文阅读

[数据结构与算法]数据结构学习(列表:五(有序列表的排序算法))

有序列表

选择排序

选择排序算法将有序列表的分为无序前缀和有序后缀两部分,此外,还要求不大于后缀,如此,只需要从前缀中挑出最大者,并作为最小元素转入后缀中,即可使有序部分的范围不断扩张。这个算法的不变性是:在任何时刻,后缀(r,n)已经有序,且不小于前缀S[0,r]。
算法初始时刻,后缀为空,不变性自然满足。于是在前缀中找出最大者,并作为首元素插入后缀,使得后缀的范围扩大,并继续保持有序。如此,该后缀的范围不断扩大,直至最终覆盖整个序列,亦即整体有序。

//对起始于位置p的n个元素进行排序
template <typename T> void List<T>::selectionSort(Posi(T) p, int n)
{
	Posi(T) head = p -> pred;
	Posi(T) tail = p;
	for(int i = 0; i < n; i++) tail = tail -> succ;//待排序区间为(head, tail)
	while(1 < n)   //在至少还有两个节点之前,在待排序区间内
	{
		Posi(T) max = selectMax(head -> succ, n);//找出最大者
		insertBefore(tail, remove(max)); //将其移至无需区间末尾(作为有序区间新的首元素)
		tail = tail -> pred; n--;
	}
}

//关于selectMax函数
template <typename T> Posi(T) List<T>::selectMax(Posi(T) p, int n)
{
	Posi(T) max = p;//最大者暂定为首节点p
	for(Posi(T) cur = p; 1 < n, n--)//从首节点出发,将后续节点逐一与max比较
		if(!lt((cur = cur -> succ) -> data, max -> data))//若当前元素不小于max,则
			max = curr; //更新最大元素位置记录
	return max; //返回最大节点位置
} 

复杂度:可以观察到,有序列表选择排序算法无论是什么情况,它的复杂度都是O(n^2)

插入排序

插入排序在我生活中经常用到,比如我们在打扑克时,每次都抽取一张牌,然后将这张牌按照顺序插入到手里已排好序的牌中,抽取完最后一张牌后,手里的牌已经是全部排好序的了。
我们可以将一个整个列表视作并切分成两部分:有序的前缀、无序的后缀。通过迭代,反复将后缀的首元素转移至前缀中,由此,可看出该算法的不变性:==在任何时刻,相对于当前节点e=S[r], 前缀S[0, r)总是有序。==算法开始时前缀为空,不变性自然满足。
可能会觉得插入排序与选择排序相差不大,但是这两者有着本质区别:选择排序中,后缀是有序的,无需前缀中的任何一个元素都是不大于后缀的;而在插入排序中,相对于有序前缀,无需后缀中的任何一个元素对于前缀中的元素可能大于小于或者是等于的。
所以插入排序的任务就是每次将后缀中的首元素依据顺序插入到相应的位置:

template <typename T> void List<T>::insertSort(Posi(T) p, int n)
{
	for(int r = 0; r < n; r++)  //逐一遍历各节点
	{
		insertAfter(search(p -> data, r, p), p -> data) //在适当位置进行插入
		p = p -> succ;  //转向下一节点
		remove(p -> pred);
	}
}

复杂度:最好O(n), 最坏O(n^2)

这里我们说一下序列中的逆序对,逆序对一定是由两个元素组成的,可可能相邻也可能不相邻。但是后者一定小于前者。为了方便统计,我们可以将每个逆序对计入后者元素的帐上,这样考察一个元素中有多少逆序对,只需考察在这个元素之前有多少各元素比它大即可。在插入排序算法中,时间复杂度主要花费在每一轮迭代中search算法里,在search算法里要进行多次比较。所以我们可以知道比较的次数s与逆序对的数量T的关系为:s = T+n,n为问题的规模,也就是列表元素个数。所以,插入排序算法的比较次数除了由问题规模决定之外,也与逆序对个数的有关系。当列表为最好情况:即整体都是有序的,那么逆序对个数为0,比较次数就为n,所以时间复杂度为O(n);当为最坏情况:逆序对个数为:n(n-1)/ 2, 所以时间复杂度为O(n^2)。
而逆序对的个数在列表输入时就已经决定。像这种时间复杂度由输入影响的算法被称之为输入敏感型算法。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-26 12:18:24  更:2021-07-26 12:19:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:21:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码