循环链表

数据结构:链表讲解

拈花ヽ惹草 提交于 2019-12-28 15:12:11
数据结构:链表讲解 一、缓存淘汰策略: 缓存的大小有限,当缓存被用满时,哪些数据应该被清理出去?哪些数据应该保留?这就需要缓存淘汰策略来决定。 简单理解: 就是当缓存被用满时清理数据的优先顺序 。 先进先出策略 FIFO(First In, First Out) 最少使用策略 LFU(Least Frequently Used) 最近最少使用策略 LRU(Least Recently Used) 以上策略举个栗子: 假如,你买了很多书,但有一天发现,书太多了,太占书房空间了,打算丢掉一些书籍; 丢到刚买的书:先进先出策略 丢到买完一直都没有读过的书:最少使用策略 丢到最近刚买的书,但是一直都没怎么读过:最近最少使用策略 二、数组与链表的区别: 1.底层存储的结构区别: 我们可以从 底层的存储结构 来看。数组需要一块 连续的内存空间 来存储,对内存的要求比较高。 如果我们申请一个 100MB 大小的数组,当内存中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于 100MB,仍然会申请失败。 链表恰恰相反,它并 不需要一块连续的内存空间 ,它通过 指针 将一组零散的内存块串联起来使用,其中,我们把内存块称为链表的 结点 。 为了将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的 下一个结点的地址 。结点地址的指针叫作 后继指针 next 。

数据结构与算法 — 链表

偶尔善良 提交于 2019-12-26 21:58:27
链表 (通过“指针”将一组零散的内存块串联起来使用。) 三种常见链表结构: 单链表:链表通过指针将一组零散的内存块串联在一起。其中,我们把内存块称为链表的“结点”。为了将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的下一个结点的地址。如图所示,我们把这个记录下个结点地址的指针叫做后继指针next 如图所示,你会发现,其中有两个结点比较特殊,他们分别是第一个结点和最后一个结点。我们习惯把第一个结点叫做头结点,把最后一个结点叫做尾结点。其中,头结点用来记录链表的基地址。有了它,我们可以遍历得到整条链表。而尾结点特殊的地方是:指针不是指向下一个结点,而是指向一个空地址NULL,表示这是链表上最后一个结点。与数组一样,链表也支持数据的查找、插入和删除操作。我们知道,进行数组的插入,删除操作时,为了保持内存的连续性,需要做出大量的数据搬移,所以时间复杂度是O(n)。而在链表中插入或者删除一个数据,我们并不需要为了保持内存的连续性而搬移结点,图中可以看出,针对链表的插入和删除操作,我们只需要考虑相邻结点的指针改变,所以对应时间复杂度是O(1)。 但是有利也有弊。链表想要随机访问第K个元素,就没有数组高效了。因为链表中的数据并非连续存储的,所以无法像数组那样,根据首地址和下标,通过寻址公式就能计算出内存地址,而是需要根据指针一个结点一个结点地依次遍历,直到找到对应的结点。所以

循环链表的运用——约瑟夫环

拜拜、爱过 提交于 2019-12-26 04:52:55
今天写循环链表里的约瑟夫环(严蔚敏版数据结构题集) 问题描述: 约瑟夫问题的一种描述是:编号为1,2,3,4……,n的n个人按顺时针方向围坐一圈,每个人持有一个密码(正整数)。一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1开始报数,如此下去,直至所有人的全部出列为止。试设计一个程序求出出列顺序。 基本要求 利用简单的单向循环列表存储结构模拟此过程,按照出列的顺序印出各人的编号。 测试数据 m的初值为20;n=7,7个人的密码分别为:3,1,7,2,4,8,4,首先m的值为6(正确的出列顺序为6,1,4,7,2,3,5)。 代码如下: #include<iostream> using namespace std; typedef struct Lnode {//定义结构体 int data; struct Lnode *next; }*Linklist; void joseph(int n,int k,int *m) { Linklist p,r,list=NULL; int i; for(i=0;i<n;i++) { p=(Linklist)malloc(sizeof(Lnode)); p->data=i+1; if(list==NULL) { r

静态链表、循环链表、双向链表(C代码实现)

本小妞迷上赌 提交于 2019-12-22 05:34:18
静态链表 对于没有指针的编程语言,可以用数组替代指针,来描述链表。让数组的每个元素由data和cur两部分组成,其中cur相当于链表的next指针, 这种用数组描述的链表叫做静态链表 ,这种描述方法叫做游标实现法。我们对数组的第一个和最后一个元素做特殊处理,不存数据。让数组的第一个元素cur存放第一个备用元素(第一个未被占用的元素)下标,而数组的最后一个元素cur存放第一个有值的元素下标,相当于头结点作用。空的静态链表如下图 当存放入一些数据时("甲""乙""丁""戊""己""庚"),静态链表为: 静态链表的插入操作 在静态链表第三个位置插入"丙"后,结果如下: 静态链表中要解决的是:如何用静态模拟动态链表结构的存储空间的分配,需要时申请,无用时释放。 其主要的思想: 我们自己定义一个内存分配函数,如Malloc_SLL(StaticLinkList space) 1 //插入元素时,分配空间的下标(从备用链表中去取出) 2 int Malloc(StaticLinkList L) 3 { 4 int i = L[0].cur; //获取备用链表的下标 5 if (i) //链表不为空 6 L[0].cur = L[i].cur; //将第一位的游标改成备用链表的下表+1 7 return i; 8 } 然后再修改游标表示,如上图 代码附上: 1 //静态链表中i位置插入一个元素

双向循环链表的创建、查找、插入、删除和遍历等操作

a 夏天 提交于 2019-12-16 03:36:46
双向循环链表的创建、查找、插入、删除和遍历等操作 # ifndef __DLINKLIST_H__ # define __DLINKLIST_H__ # include <stdio.h> # include <stdlib.h> typedef int datatype ; typedef struct double_link_node { datatype data ; struct double_link_node * prior , * next ; } dlk , * dplk ; extern void init_dlinklist ( dplk * H ) ; extern void create_dlinklist ( dplk p ) ; extern void search_dlinklist ( dplk p , int pos , dplk * r ) ; extern void insert_dlinklist ( dplk p , datatype val , int pos ) ; extern void delete_dlinklist ( dplk p , int pos ) ; extern void show_dlinklist ( dplk p ) ; extern void clear_dlinklist ( dplk p ) ; #

数据结构 ---- 单向循环链表

末鹿安然 提交于 2019-12-15 21:20:15
单向循环链表 单链表的一个变形是单向循环链表,链表中最后一个节点的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_empty ( ) : return 0 count = 1 cur = self .

golang数据结构之循环链表

末鹿安然 提交于 2019-12-09 19:42:09
循环链表还是挺有难度的: 向链表中插入第一条数据的时候如何进行初始化。 删除循环链表中的数据时要考虑多种情况。 详情在代码中一一说明。 目录结构如下: circleLink.go package link import ( "fmt" ) type CatNode struct { ID int Name string next *CatNode } func InserCatNode(head *CatNode, newCatNode *CatNode) { //初始化链表 //头结点一开始是空的,当插入第一条数据时,进行初始化 if head.next == nil { head.ID = newCatNode.ID head.Name = newCatNode.Name head.next = head return } //定义一个临时变量,找到环形的末尾,方便以后进行插入 tmp := head for { if tmp.next == head { tmp.next = newCatNode newCatNode.next = head break } else { tmp = tmp.next } } } func DeleteCatNode(head *CatNode, id int) *CatNode { //建立一个节点指向头结点 tmp := head /

LinkedList源码学习

醉酒当歌 提交于 2019-12-06 13:04:55
 今天来介绍下LinkedList,LinkedList与ArrayList一样实现List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList是List接口链表的实现。基于链表实现的方式使得LinkedList在插入和删除时更优于ArrayList,而随机访问则比ArrayList逊色些。 构造图如下: 蓝色线条:继承 绿色线条:接口实现 LinkedList是基于链表结构的一种List,在分析LinkedList源码前有必要对链表结构进行说明。  链表是由一系列非连续的节点组成的存储结构,简单分下类的话,链表又分为单向链表和双向链表,而单向/双向链表又可以分为循环链表和非循环链表,下面简单就这四种链表进行图解说明。 1.1.单向链表 单向链表就是通过每个结点的指针指向下一个结点从而链接起来的结构,最后一个节点的next指向null。 1.2.单向循环链表 单向循环链表和单向列表的不同是,最后一个节点的next不是指向null,而是指向head节点,形成一个“环”。 1.3.双向链表 从名字就可以看出,双向链表是包含两个指针的,pre指向前一个节点,next指向后一个节点,但是第一个节点head的pre指向null,最后一个节点的tail指向null。 1.4.双向循环链表 双向循环链表和双向链表的不同在于,第一个节点的pre指向最后一个节点

单链表及其基本操作

Deadly 提交于 2019-12-06 03:51:38
1 链表的概念及结构 概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 实际中链表的结构非常多样,以下情况组合起来就有8种链表结构: 1. 单向、双向 2. 带头、不带头 3. 循环、非循环。 常用的有无头单向非循环链表、带头双向循环链表。 1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结 构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。 2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向 循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而 简单了,后面我们代码实现了就知道了。 下面是无头单向非循环链表的一些基本操作代码: //NodeList.c #include"NodeList2.h" //遍历 void print(Node* head) { Node* cur = head; //声明一个新指针用来进行遍历 while (cur) { //cur为NULL时链表遍历完 printf("%d-->", cur->val); cur = cur->next; } printf("\n"); } //销毁链表 Node* NodeListDestory(Node* head

day57

一笑奈何 提交于 2019-12-06 03:33:46
目录 ORM查询优化 only与defer查询优化 only: defer: select_related与prefetch_ralated select_related: prefetch_ralated: MTV与MVC模型 choices参数 Ajax简介 前端和后端数据编码格式 ajax发送json数据格式 ajax发送文件格式数据 序列化 ORM查询优化 only与defer查询优化 减轻数据库的压力 only: only括号内放 字段,查询结果是一个列表套一个个数据 对象 这些数据对象点括号的字段属性不会再查询数据库, 直接就是对象获取属性 也支持点击括号内没有的字段,但是每点击一次就会重新走一次数据库查询 缺点:效率极低 实例: res = models.Book.objects.only('title') #print(res) #拿到对象 数据库语句只走一次 for i in res: print(i.title) #拿到数据所有书名 走一次数据库语句 print(i.price) #走5次数据库查询语句,第1次是总体的查询语句,后面4条是4条书籍字段的语句 defer: 实例: res = models.Book.objects.defer('title') #print(res) #打印的结果是列表套对象,走一条数据库语句 for i in res: