《算法基础》——3.5 链表算法

3.5 链表算法

到目前为止,本章描述了一些用于建立和维护链表的算法,包括在链表的开头、结尾和中间添加项的算法,查找链表中项的算法和从链表中删除项的算法。
以下各节描述了利用其他方式来操作链表的算法。
3.5.1 复制链表
一些算法重新排列链表。本节和下一节将描述一些对链表中的项进行排序的算法。如果想保持原来链表的顺序,就必须在排序之前就做一个该链表的副本。
下面的伪代码演示了如何复制一个单链表:

该算法相当简单,但有一点值得一提:该算法使用last_added来跟踪最新被加入到链表副本中的单元格。当要把一个项插入到链表中时,该算法将last_added.Next指向一个新的单元格对象。这使新的对象在该链表的末尾。然后该算法更新last_added以指向新单元格并将原始单元格的值赋予它。
这允许链表从底部而不是从顶部增长。如果如同3.10节“练习1”中的所描述的那样:跟踪链表的最后一个项,类似于如何轻松地将项添加到链表的末尾。
3.5.2 链表的插入排序
在第6章中谈到了许多关于排序的算法,但是其中有两种算法值得在这里进行讨论:选择排序(我们将在下一节中进行描述)和插入排序。
排序算法的基本思想是把一个单元格从待输入链表中提取出来,并将其插入到一个已经排好序的链表(其最初开始是空的)中的适当位置。
下面的伪代码展示了插入排序算法,这里的待排序的各个单元格被存储在一个具有top哨兵的单向链表中:

该算法开始通过建立一个空的链表来保存排序的输出。然后,它从一个无序的输入链表的头至尾进行循环。对于每个输入单元格,算法遍历前面已经排好序的链表来找到一个新单元格对应的位置。然后,它把新单元格插入。
如果调用之前的3.2.6节中描述的插入单元格算法InsetCell,可以简化代码。
如果输入链表中的单元格已经按照从大到小的顺序排列好,该算法只需用短短的几个步骤就可以实现从链表开头插入一个新单元格。如果链表保存N个单元格,在新的链表中插入的所有项总共需要O(N)的步骤。这是该算法的最佳情况。
如果在输入链表中单元格已经从小到大排序,这种算法必须从新的链表的末尾插入每个单元格。而对于每次插入一个链表都需要查找已有链表的末尾单元格。因此,插入所有项需要1+2+3+…+N=N×(N+1)÷2=O(N2)的步骤。
在平均情况下,要插入的项是随机排列的,该算法可以快速插入一些项,但其他项需要更长的时间。其结果是,该算法的运行时间仍然是O(N2),虽然实际上它不会需要最坏情况所需的时间。许多其他的排序算法只需要O(N log N)的时间,而这种算法的时间复杂度为O(N2),表现则相对缓慢。这使得该算法面对数据量较大的链表表现无力。然而,它在数据量较小的链表中运行很快,并且它适用于链表,许多其他的算法并不适用于链表。

时间: 2024-09-02 09:03:18

《算法基础》——3.5 链表算法的相关文章

java 算法基础之二快速排序算法

http://www.cnblogs.com/hexiaochun/archive/2012/09/03/2668324.html java 算法基础之二快速排序算法 所谓的快速排序的思想就是,首先把数组的第一个数拿出来做为一个key,在前后分别设置一个i,j做为标识,然后拿这个key对这个数组从后面往前遍历,及j--,直到找到第一个小于这个key的那个数,然后交换这两个值,交换完成后,我们拿着这个key要从i往后遍历了,及i++;一直循环到i=j结束,当这里结束后,我们会发现大于这个key的值

数据结构之自建算法库——循环单链表

本文针对数据结构基础系列网络课程(2):线性表中第13课时循环链表. 按照"0207将算法变程序"[视频]部分建议的方法,建设自己的专业基础设施算法库. 双链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:clinklist.h,包含定义双链表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef CLINKLIST_H_INCLUDED #define CLINKLIST_H_INCLUDED //循环单链表基本运算函数 typedef int Elem

数据结构之自建算法库——循环双链表

本文针对数据结构基础系列网络课程(2):线性表中第13课时循环链表. 按照"0207将算法变程序"[视频]部分建议的方法,建设自己的专业基础设施算法库. 双链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:cdlinklist.h,包含定义双链表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef CDLINKLIST_H_INCLUDED #define CDLINKLIST_H_INCLUDED //循环双链表基本运算函数 typedef int E

《算法基础》——第1章 算法基础知识 1.1 方法

第1章 算法基础知识 在开始算法学习之前,你需要一点背景知识.简单地说,首先需要知道的是算法是完成某些事情的方法.它定义了用某个方法执行一个任务的步骤.这个定义看起来足够简单,但是没有人为了做一件十分简单的工作而写算法.没有人写指令来获取数组中的第四个元素.这只是假设这是一个数组定义的一部分,并且你知道怎么去做(如果你知道如何在这个问题中使用编程语言).一般来说,人们只是为了完成复杂的任务而写算法.算法解释了如何找到一个复杂代数问题的答案,如何在一个包含数千条街道的网络中找到最短路径,抑或是如何

《算法基础》——3.2 单链表

3.2 单链表 在一个单链表中,每个单元格由一个单链路连接到下一个单元格.图3-1所示的链表即是单链表. 如果要使用一个链表,就需要一系列算法来遍历链表.将项添加到链表中.查找链表中的项.删除链表中的项.以下各节将描述一些可能需要使用的算法.3.2.1 遍历链表 假设一个程序已经建立了一个链表,遍历它的单元格是比较容易的.下面的算法展示了如何遍历链表中的单元格,并使用某种方法对单元格中的值进行处理.本例中使用Print方法来显示单元格的值,但也可以用其他任何方法来代替Print方法对单元格进行操

《算法基础》——第3章 链表 3.1 基本概念

第3章 链表 链表可能是程序员会建立的最简单的数据结构.然而,用来构建它们所需用到的某些概念也会被用来构建这本书里描述的最复杂的数据结构.要使用一个链表,除了了解查找,插入和删除单元格的方法以外,还需要了解单元格和链接.可以使用这些相同的概念来构建复杂的网络.易被混淆的树和平衡树.本章说明了为使用链表所需要掌握的方法.后面的章节中(特别是第4章.第5章.第8章和第10-14章)会重温这些方法. 3.1 基本概念 链表是由通常被称为单元格的对象构建而成.单元格类包含链表必须存储的数据和到另一个单元

《算法基础》——3.6 链表的选择排序

3.6 链表的选择排序 该选择排序算法背后的基本思想是:搜寻输入链表中所包含的最大项,然后将其添加到一个不断增长的有序链表的前面.下面的伪代码显示了选择排序算法的单向链表实现方法(默认其中的项是整数类型): 如果将寻找输入链表中最大单元格的代码抽取出来,作为一个新的算法,然后在原有算法中调用该新算法,则可以使得上面的算法变得更加简化.若输入链表包含K个项,则寻找链表中的最大项需要花费K步.在算法进行的过程中,输入链表将会缩小规模.因此,如果它最初拥有N个项,步骤的总数是N+(N-1)+(N-2)

《算法基础》——3.4 有序链表

3.4 有序链表 有时,让链表中的项保持有序是十分方便的.当将一个新项加入有序链表时,需要搜索链表来找到该项所属位置,并更新相应的链接来插入该项.下面的伪代码显示了在一个有序链表中插入一个项的算法: 在最坏的情况下,该算法可能需要遍历整个链表为新项找到正确的位置.因此,如果该链表保存N个单元格,其运行时间为O(N).虽然不能提高理论运行时间,但是可以通过添加底端哨兵使算法更简单而且在实际运行中更加快速.如果将底部哨兵的Value设定成一个比单元格中任意可能存储的Value值都大的值,就可以删除对

[C++ 面试基础知识总结] 泛型算法

[C++ 面试基础知识总结] 泛型算法 参考书籍:<C++ Primer> 目录 C 面试基础知识总结 泛型算法 目录 基础泛型算法 只读算法 写容器算法 重排容器元素算法 定制操作 向算法传递函数 lambda表达式 参数绑定 特殊迭代器 插入迭代器 iostream迭代器 反向迭代器 5类迭代器 链表的特定容器算法 基础泛型算法 泛型算法本身运行于迭代器之上,不会执行容器的操作,可以改变容器中保存元素的值,也可以在容器内移动元素,但永远不会直接添加或删除元素.插入迭代器是一种特殊的迭代器,