循环链表

【Python数据结构与算法笔记day18】3.2. 单项循环链表

坚强是说给别人听的谎言 提交于 2020-02-02 02:55:00
文章目录 3.2. 单项循环链表 单向循环链表 操作 实现 3.2. 单项循环链表 单向循环链表 单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点。 操作 is_empty() 判断链表是否为空 length() 返回链表的长度 travel() 遍历 add(item) 在头部添加一个节点 append(item) 在尾部添加一个节点 insert(pos, item) 在指定位置pos添加节点 remove(item) 删除一个节点 search(item) 查找节点是否存在 实现 class Node ( object ) : """节点""" def __init__ ( self , item ) : self . item = item self . next = None class SinCycLinkedlist ( object ) : """单向循环链表""" def __init__ ( self ) : self . _head = None def is_empty ( self ) : """判断链表是否为空""" return self . _head == None def length ( self ) : """返回链表的长度""" # 如果链表为空,返回长度0 if self . is

数据结构之带头双向循环链表(源代码)

旧街凉风 提交于 2020-01-31 02:34:17
List.h //带头双向循环链表 # ifndef __LIST_H__ # define __LIST_H__ # include <stdio.h> # include <stdlib.h> # include <assert.h> # include <malloc.h> typedef int LTDataType ; typedef struct ListNode { LTDataType _data ; struct ListNode * _next ; //后继 struct ListNode * _prev ; //前驱 } ListNode ; typedef struct List { ListNode * _head ; } List ; void ListNodeInit ( List * plist ) ; void ListNodeDestory ( List * plist ) ; void ListNodePrint ( List * plist ) ; void ListNodePushBack ( List * plist , LTDataType x ) ; void ListNodePopBack ( List * plist ) ; void ListNodePushFront ( List * plist , LTDataType x

维吉尼亚加密算法 (C语言实现简单的加密算法) ------- 算法笔记007

限于喜欢 提交于 2020-01-29 16:16:07
概念理解 什么是维吉尼亚加密算法 加密步骤:1.创建一个匹配循环链表;2.接受需要加密的明文;3.根据随机生成的密钥配合链表进行移位;4.输出/保存对应的密文 解密步骤: 1.接受加密后的密钥;2.根据密文找到对应的匹配值,通过密钥进行逆移位操作找到明文输出 总的来说维吉尼亚加密算法就是对循环链表的查找操作 这里我们来模拟a-z实现加密操作 我们输入changlon,然后生成随机密钥,进行加密操作 如:字符c,随机生成的密钥为2 我们找到a-z循环链表中的c字符位置,向后查找2个单位指到e的位置,e就是对应c的密文 注:图中的A-Z大写链表理解为a-z的小写链表,整个链表是循环的 实现代码 匹配链表结构定义 //双向循环链表结构 typedef struct doulNode { char data ; struct doulNode * next ; //指向下一个节点 struct doulNode * prior ; //指向上一个节点 } Doul , * DoulList ; 创建一个匹配链表 //Status ,ok,error是宏定义int ,1,0 Status createLink ( DoulList * L ) { ( * L ) = ( DoulList ) malloc ( sizeof ( Doul ) ) ; ( * L ) -> next = ( *

数据结构第五篇——线性表的链式存储之循环链表

你说的曾经没有我的故事 提交于 2020-01-25 05:23:34
♥注:未经博主同意,不得转载。   链表是另一种形式的链式存储结构,它是线性链表的一种变形。在线性链表中,每个结点的指针都指向它的下一个结点,最后一个结点的指针域为空,表示链表的结束。若使最后一个结点的指针指向头结点,则链表呈环状,这样的链表称为 循环链表 。 循环链表当然也分为 单链表 和 双向列表 。 通常情况下,在循环链表中设立尾指针而不设头指针,可使某些操作简化。 循环链表的定义和操作与单链表类似,只是循环结束条件有所不同,下面只给出单循环链表的定义和部分操作,至于双向循环链表可能会在以后的项目中出现,到时再进一步探讨。 单循环链表定义如下: 1 typedef int Data; 2 3 struct Node 4 { 5 Data data; //数据 6 Node* next; //指向后继的指针 7 }; 8 9 class CList 10 { 11 Node* head; //创建头结点 12 public: 13 CList() //构造函数 14 { 15 head = new Node; 16 head->next = head; //头尾相接 17 } 18 ~CList(); //析构函数 19 20 Data GetElem(int i); //取第i个元素的值 21 bool IsEmpty(); //判断是否为空链表 22 void Create

数据结构之链表

雨燕双飞 提交于 2020-01-25 04:46:34
数据需要一块连续的内存空间来存储,对内存的要求比较高。而链表恰恰相反,它并不需要一块连续的内存空间,它通过“ 指针 ”将一组 零散 的内存块串联起来使用。 最常见的链表:单链表、双链表、和循环链表。 单链表 结点 :除了存储数据之外,还要记录链上的下一个节点的地址,如下图,我们把这个记录下个结点地址的指针叫作 后继指针 next 头结点 :用来记录链表的基地址。 尾结点 :指向一个空地址 NULL 针对链表的插入和删除操作,只需考虑相邻结点的指针改变,所以对应的时间复杂度是O(1)。 链表想要随机访问第k个元素,就没有数组那么高效,链表的数据并非连续存储的,所以无法像数组那样,根据首地址和下标通过寻址公式就能直接计算出对应的内存地址,而是要根据指针一个结点一个结点的一次遍历,直到找到相应的结点。需要 O(n)时间复杂度 。 循环链表 是一种特殊的单链表。它和单链表唯一的区别就在尾结点。循环链表的 尾结点指针是指向链表的头结点 。 当处理的数据具有环形结构特点时,就特别适合采用循环链表。 双向链表 双向链表支持双向遍历,它需要额外的两个空间来存储后继结点和前驱结点的地址。 时空替换思想 :“用空间换时间” 与 “用时间换空间” 当内存空间充足的时候,如果我们更加追求代码的执行速度,我们就可以选择空间复杂度相对较高,时间复杂度小相对较低的算法和数据结构,缓存就是空间换时间的例子

数据结构-链表

帅比萌擦擦* 提交于 2020-01-25 04:45:25
数组需要一块连续的内存用来存储数据,而链表恰恰相反,它并不需要一块连续的内存,它通过指针将不连续的内存块串起来。 链表结构很多,我们说下最常见的,单链表,双向链表和循环链表。 我们先看比较简单的 单链表 如上图可以看出来,图中的每个节点不仅需要存储数据,还需要记录一个指向下一个节点的指针,如图所示,我们把记录下一个节点的指针叫做后继指针 next 图中有两个节点比较特殊第一个节点我们叫做头节点,最后一个节点我们叫做尾结点,头节点记录了这个链表的基地址,尾节点的指针不是指向一个节点,而是指向一个空地址NULL。 我们知道在数组的插入和删除操作后,为了保持连续内存的特点需要搬移大量数据,而在链表中我们不需要保持连续内存的结构,所有我们在链表中插入和删除操作时时间要比在数组中操作删除添加速度快, 针对链表的插入和删除操作可以看下图 但是有利就有弊,在链表中查询数据的时候就没有数组那么快了,在数组中可以首地址和下标可以很快查出来,因为是连续的,但是在链表中由于不是连续的,我们就需要根据指针节点一个一个遍历才能查询出需要的数据。 接下来我们看下循环链表,其实循环链表就是一种特殊的单链表 循环链表就是尾结点指向链表的头节点,而不是指向一个空值,有点就是从链表尾部查询到链表头部很方便,在处理某些特殊的数据结构时很有用处。 最后我们在看下 双向链表 单链表只有一个方向

数据结构基础温故-1.线性表(下)

痴心易碎 提交于 2020-01-25 04:39:08
在 上一篇 中,我们了解了单链表与双链表,本次将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表(circular linked list)。 一、循环链表基础 1.1 循环链表节点结构   循环链表和单链表的主要差异就在于 循环的判断条件 上,原来是判断p.next是否为空,现在则是p.next不等于头结点,则循环未结束。 1.2 循环链表的O(1)访问时间   在单链表中,有了头结点,我们可以在O(1)时间访问到第一个节点,但如果要访问最后一个节点却需要O(n)的时间,因为我们需要对整个链表进行一次遍历。在循环链表中,我们可以借助尾节点来实现,即不用头指针,而是 用指向终端结点的尾指针来表示循环链表 ,这时候无论是查找第一个节点还是最后一个节点都很方便,可以控制在O(1)的时间内,如下图所示。   从上图中可以看到,终端结点用尾指针(tail)指示,则查找终端结点是O(1),而开始结点,其实就是tail.Next,其时间复杂也为O(1)。由此也可以联想到,在合并两个循环链表时,只需要修改两个链表的尾指针即可快速地进行合并。 二、循环链表实现 2.1 循环链表节点的定义实现 public class CirNode<T> { public T Item { get; set; } public

线性表->链式存储->双向链表

我怕爱的太早我们不能终老 提交于 2020-01-25 04:36:22
文字描述   之前的链表(单链表、循环链表)的链式存储结构中只有一个指示直接后继的指针域。由此,从某个结点出发只能顺指针往后寻查其他结点。若要寻查结点的直接前驱,则需从表头指针出发。即单链表中,NextElem的执行时间为1,而PriorElem的执行时间为n。为了克服单链表这种缺点,可利用双向链表。   在双向链表中,每个节点有两个指针域,一个指向其直接后继,一个指向其直接前驱。 示意图 算法分析 插入、删除、查找、求后继等同单链表。但是求前驱不一样,其时间复杂度为1。 代码实现 1 // 2 // Created by lady on 19-1-31. 3 // 4 5 #include <stdlib.h> 6 #include <stdio.h> 7 #include <string.h> 8 9 //线性表的双向循环链表存储结构 10 typedef struct ElemType{ 11 char data[10]; 12 }ElemType; 13 typedef struct DuLNode{ 14 ElemType e; 15 struct DuLNode *prior; 16 struct DuLNode *next; 17 }DuLNode, *DuLinkList; 18 19 //构造一个空的双向循环链表 20 static int InitList

数据结构------线性表

时光毁灭记忆、已成空白 提交于 2020-01-24 18:56:31
知识框架: --- 顺序存储(逻辑相邻物理相邻)-----------------------------顺序表 - - ---单链表(指针实现) 线性表(逻辑结构) - ----双链表(指针实现) -链式存储(逻辑相邻的但物理不)-----------------------------循环链表(指针实现) ----静态链表(数组实现) 1、线性表的特点: 1 表中元素个数有限 2 元素有先后测序性 逻辑相邻 3 元素类型相同 每个元素占大小相同的存储空间 4 线性表是逻辑结构 顺序表和链表都是存储结构 线性表逻辑相邻 顺序表物理相邻 链表 物理不一定相邻,线性表中每个元素除开始元素外只有一个前驱 2、链表注意要点: 1 头指针和头结点的区分 : 不管带不带头结点,头指针始终指向链表的第一个结点,如果带头结点,则头指针指向它,通常头结点不存储信息。 头指针的意义在于,在访问链表时,总要知道链表存储在什么位置(从何处开始访问),由于链表的特性(next指针),知道了头指针,那么整个链表的元素都能够被访问,也就是说头指针是必须存在的 2 单链表添加头节点的好处 :(如果带头结点的单链表 head.next()为空则链表空) a 、 对链表头的操作 和 其他位置的操作一致,不必分情况处理,头结点和其他内部结点处理统一 b、 无论链表是否为空,其头指针是指向头结点的非空指针

数据结构(四)之循环链表

坚强是说给别人听的谎言 提交于 2020-01-22 08:33:13
循环链表 循环链表:是另一种形式的链式存储结构.他的特点是表中 最后一个节点的指针域指向头节点 ,整个链表形成一个环.由此,从表中任一节点出发均可找到表中其他的节点,如下图所示为单链表的循环链表.类似的,还可以有多重链的循环链表. 循环链表的操作和线性链表基本一致,差别仅在于算法中的循环条件不是尾节点的next为null,而是他们是否等于头指针.但有的时候,若在循环链表中设立尾结点,而不设头节点,可使某些操作简化。例如要将两个线性表合并成一个线性表时,仅需将一个表的尾和另一个表头相连,如下图所示,这个操作只需改变指针即可,运算时间为O(1),合并后如下图所示. 注意这里为循环链表 所以在输出的时候 就的判断什么时候跳出循环? 当尾节点 的next 域 指向头节点的时候; 合并 循环链表 package main . com . cs . test ; import main . com . cs . link . LinkList ; public class CycleLinkList < T > { private Node < T > head ; //链表的头节点 private Node < T > tail ; //链表的尾节点 /** * 构造一个空链表 */ public CycleLinkList ( ) { head = tail = null ; } /**