精华内容
下载资源
问答
  • 双向链表的应用

    2020-07-14 21:48:38
    双向链表的应用 1.使用带head头的双向链表实现 2.双向链表可以前后查找因为有pre,单向链表只能一个方向 3.增删方便,改查方便,利用编号; 【注】:因为查询和单链表类似所以就省去了双链表的查询。 package ...

    双向链表的应用
    1.使用带head头的双向链表实现
    2.双向链表可以前后查找因为有pre,单向链表只能一个方向
    3.增删方便,改查方便,利用编号;

    【注】:因为查询和单链表类似所以就省去了双链表的查询。
    package LinkedList;
    
    public class DoubleLinkedListTest {
       
    	public static void main(String[] args) {
       
    		PersonNode p1 = new 
    展开全文
  • 双向链表及其用法

    万次阅读 多人点赞 2018-05-25 13:40:46
    转载自:https://blog.csdn.net/fk5431/article/details/45072935一、双向链表的定义双向链表也...二、双向链表的存储结构双向链表也是采用的链式存储结构,它与单链表的区别就是每个数据结点中多了一个指向前驱元素...

    转载自:https://blog.csdn.net/fk5431/article/details/45072935


    一、双向链表的定义

    双向链表也是链表的一种,它每个数据结点中都有两个结点,分别指向其直接前驱和直接后继。所以我们从双向链表的任意一个结点开始都可以很方便的访问其前驱元素和后继元素。

    二、双向链表的存储结构

    双向链表也是采用的链式存储结构,它与单链表的区别就是每个数据结点中多了一个指向前驱元素的指针域 ,它的存储结构如下图:

    当双向链表只有一个结点的时候它的存储结构如下:

     

    三、双向链表的实现与操作

    因为在双向链表中,我们可以通过任意一个结点访问到其前驱元素和后继元素,时间复杂度为O(1),所以双向链表是十分方便的,我们通常构建链表也会选择去构建双向链表。

    接下来看一下双向链表的实现与操作:

    [cpp]  view plain  copy
    1. #include<stdio.h>  
    2. #include<stdlib.h>  
    3. #include<malloc.h>  
    4. typedef struct DOUBLE_LIST  
    5. {  
    6.     int data;  
    7.     struct DOUBLE_LIST *prev;  
    8.     struct DOUBLE_LIST *next;  
    9. }double_list;  
    10. double_list *createlist()       //创建有n个元素的双向链表 并输入元素  
    11. {  
    12.     double_list *head, *p, *q;  
    13.     int n,x;  
    14.     head = (double_list *)malloc(sizeof(double_list));  
    15.     head->prev = head;  
    16.     head->next = head;  
    17.     p = head;  
    18.     printf("输入要创建双向链表的元素的个数:\n");  
    19.     scanf("%d",&n);  
    20.     for(int i=0;i<n;i++)  
    21.     {  
    22.         scanf("%d", &x);  
    23.         q = (double_list *)malloc(sizeof(double_list));  
    24.         q->data = x;  
    25.         p->next = q;  
    26.         head->prev = q;  
    27.         q->prev = p;  
    28.         q->next = head;  
    29.         p = q;  
    30.     }  
    31.     return head;  
    32. }  
    33. //遍历并且输出这些元素  
    34. void printlist(double_list *head)  
    35. {  
    36.     double_list *p;  
    37.     p = head;  
    38.     p = p->next;  
    39.     while(p!=head)  
    40.     {  
    41.         printf("%d  ", p->data);  
    42.         p = p->next;  
    43.     }  
    44.     printf("\n");  
    45. }  
    46. //得到现在双向链表中的元素的个数  
    47. int lengthlist(double_list *head)  
    48. {  
    49.     double_list *p;  
    50.     p = head;  
    51.     p = p->next;  
    52.     int coun = 0;  
    53.     while(p!=head)  
    54.     {  
    55.         coun++;  
    56.         p = p->next;  
    57.     }  
    58.     return coun;  
    59. }  
    60. //在第i个元素之前插入数据data  
    61. void insertlist_f(double_list *head, int i, int data)  
    62. {  
    63.     double_list *p = head, *q;  
    64.     p = p->next;  
    65.     i--;  
    66.     while(i--)  
    67.         p = p->next;  
    68.     q = (double_list *)malloc(sizeof(double_list));  
    69.     q->data = data;  
    70.     (p->prev)->next = q;  
    71.     q->prev = p->prev;  
    72.     q->next = p;  
    73.     p->prev = q;  
    74. }  
    75. //删除第i个位置的元素  
    76. void deletelist_i(double_list *head, int i)  
    77. {  
    78.     double_list *p = head;  
    79.     p = p->next;  
    80.     i--;  
    81.     while(i--)  
    82.         p = p->next;  
    83.     (p->prev)->next = p->next;  
    84.     (p->next)->prev = p->prev;  
    85.     free(p);  
    86. }  
    87. //删除值为x的元素  
    88. void deletelist_x(double_list *head, int x)  
    89. {  
    90.     double_list *p = head, *q;  
    91.     p = p->next;  
    92.     while(p!=head)  
    93.         if(p->data == x)  
    94.         {  
    95.             q = p->next;  
    96.             (p->prev)->next = p->next;  
    97.             (p->next)->prev = p->prev;  
    98.             free(p);  
    99.             p = q;  
    100.         }  
    101.         else  
    102.             p = p->next;  
    103. }  
    104. //对双向链表进行排序  
    105. void sortlist(double_list *head)  //升序  
    106. {  
    107.     double_list *p = head, *q, *t;  
    108.     p = p->next;  
    109.     for(;p!=head;p=p->next)  
    110.         for(t = p->next;t!=head;t=t->next)  
    111.         {  
    112.             if(p->data > t->data)  
    113.             {  
    114.                 int a = p->data;  
    115.                 p->data = t->data;  
    116.                 t->data = a;  
    117.             }  
    118.         }  
    119. }  
    120. int main()  
    121. {  
    122.     double_list *head;  
    123.     head = createlist();  
    124.     deletelist_x(head, 2);  
    125.     //sortlist(head);  
    126.     printlist(head);  
    127.     insertlist_f(head, 2, 2);  
    128.     printlist(head);  
    129.   
    130.     return 0;  
    131. }  

    对于双向链表的遍历来说我只给出了前序遍历的代码,没有写后序遍历的代码,这其实是差不多的,但是因为双向链表可以进行两个方向的遍历,这给我们带来了很大的方便。

    展开全文
  • 链表是线性表的一种,所谓的线性表包含顺序线性表和链表,顺序线性表是用数组实现的,在内存中有顺序排列,通过...而链表又包括单向链表、双向链表和循环链表,这篇文章主要学习单向链表和双向链表的原理及其相关实现。

    其实要解决一个问题得从以下几个方面入手?即在日常生活中的几大“w”,链表是什么?它有什么作用?怎么实现?在日常生活中有哪些实际应用?只要解决了这些问题,那么链表这个问题就会很清晰明了了。

    (一)什么是链表?

    链表是线性表的一种,所谓的线性表包含顺序线性表和链表,顺序线性表是用数组实现的,在内存中有顺序排列,通过改变数组大小实现。而链表不是用顺序实现的,用指针实现,在内存中不连续。意思就是说,链表就是将一系列不连续的内存联系起来,将那种碎片内存进行合理的利用,解决空间的问题。

    所以,链表允许插入和删除表上任意位置上的节点,但是不允许随即存取。链表有很多种不同的类型:单向链表、双向链表及循环链表。

    1、那么先从单向链表着手,先看看单向链表的模拟图:


    单向链表包含两个域,一个是信息域,一个是指针域。也就是单向链表的节点被分成两部分,一部分是保存或显示关于节点的信息,第二部分存储下一个节点的地址,而最后一个节点则指向一个空值。

    2、双向链表:


    从上图可以很清晰的看出,每个节点有2个链接,一个是指向前一个节点(当此链接为第一个链接时,指向的是空值或空列表),另一个则指向后一个节点(当此链接为最后一个链接时,指向的是空值或空列表)。意思就是说双向链表有2个指针,一个是指向前一个节点的指针,另一个则指向后一个节点的指针。

    3、循环链表:


    循环链表就是首节点和末节点被连接在一起。循环链表中第一个节点之前就是最后一个节点,反之亦然。

    参考:http://zh.wikipedia.org/wiki/链表

    (二)链表有什么作用?

    链表本质上就是一种数据结构,主要用来动态放置数据。也可用来构建许多数据结构,比如堆栈、队列及它们的派生。

    (三)链表的实现?

    1、单向链表的实现

    (1)单向链表的创建过程:

    第一步:定义节点的数据结构;

    第二步:创建一个空表。

    第三步:利用malloc()向系统申请分配一个节点。

    第四步:将新节点的指针成员赋值为空。若是空表,将新节点连接到表头;若是非空表,将新节点连接到表尾。

    第五步:判断是否有后续节点,如有则转入第三步,否则结束。

    (2)单向链表的输出过程:

    第一步:找到表头。

    第二步:若为非空表,则输出节点的值成员,是空表则退出。

    第三步:跟踪链表,找到下一节点的地址。

    第四步:转到第二步。

    #include <stdio.h>
    #include <conio.h>
    
    struct date//申明结构体
    {
    	char str;
    	date *prior; 
    	date *next;//用来指向下一个结构体指针
    };
    
    int main()
    {
    	date *pS,*pE,*head;//定义三个结构体指针,head用来保存链头,pE保存链尾
    	date *Rhead = NULL;//定义读取结构体指针
    	pE = head;//刚开始没有任何结点,指向表头
    	char temp;
    	scanf("%c",&temp);
    	if(temp != '#') 
    	{
    		head = new date;//新建结点
    		head->str = temp;//给新结点赋值数据
    		head->prior = NULL;
    		head->next = NULL;
    		pS = head; 		
    	} 
    	
    	scanf("%c",&temp);
        while (temp != '#')
    	{
    			pS = new date;//新建结点
    			pS->str = temp;//给新结点赋值数据
    			pS->prior = pE;
    			pS->next = NULL;//让指向下一个为空(新结点,也就是新链尾)
    			pE->next = pS;//把新结点连接到链尾
    			pE = pS;//新结点成为了新的链尾
    	}
    	printf("\n刚才输入的是:\n");
    	Rhead = head;//取得链头
    	/*
    		当然也可以直接用head不过这样就会改变其值,而无法再次查找链表
    		切忌链头的重要性,只要找不到链头,整条链表就没用!
    	*/
    	while (Rhead != NULL)//循环到链尾
    	{
    		printf("%c",Rhead->str);
    		if (Rhead!=NULL)
    		{
    			Rhead = Rhead->next;//让其指向下一个链表
    		}
    	}
    
    	printf("\n");
    	getch();
    	return 0;
    }

    以上程序代码参考http://blog.csdn.net/duke56/article/details/5764614,比起其他实现,这个很直观明了。

    2、双向链表的实现

    #include"stdio.h"
    #include"stdlib.h"
    
    typedef int DataType;//双向链表中数据的类型
    typedef struct DNode
    {
    	DataType element;
    	struct DNode *prior,*next;
    }DNode,*DoubleList;//定义双向链表中一个节点
    
    DoubleList createDList()//创建双向链表
    {
    	DoubleList head,p1,p2;
    	DataType data;
        scanf("%d",&data);
    	if(data!=0)//初始化头结点
    	{
    		head=(DoubleList)malloc(sizeof(DNode));
    		head->element=data;            //         head
    		head->prior=NULL;      //----------------------
    		head->next=NULL;       //|prior| data |  next |
    		p1=head;               // -----------------------
    	}                              //         p1
    	else                       
    	{
    		return NULL;//如果是0的话,直接跳出去,后面的工作一律不再进行
    	}
    	scanf("%d",&data);
    	while(data!=0)                                       
    	{                                            //        head             p2                 
    		p2=(DoubleList)malloc(sizeof(DNode));//-----------------   -----------------    
    		p2->element=data;                    //|prior|data|next|-->|prior|data|next| 
    		p2->prior=p1;                        //-----------------    -----------------  
    		p2->next=NULL;                       //                           p1
    		p1->next=p2;                                                              
    		p1=p2;                               
    		scanf("%d",&data);                   //其实p1的作用就是为了把后面的
    	}                                            //节点依次连接到双向链表的尾部
    		return head;                             
    }                                            
    
    DoubleList delDList(DoubleList head,DataType data)//删除链表某个节点,该节点的值等于data
    {
    	DoubleList p;
    	if(head==NULL)
    	{
    	return NULL;
    	}
    	if(data==0)
    	{
    		printf("please input the data which will be deleted!\n");
    		scanf("%d",&data);
    	}
    		p=head;//让p指向头结点,p在双向链表上移动,完成相应的操作
    	while(p!=NULL&& p->element!=data)//用p->element!=data而不是p->element=data,
    	{                                //是想让p在循环的控制下,在双向链表上不断移动
    		p=p->next;
    	}
    	if(p!=NULL)
    	{
    	if(p==head)//如果第一次的时候就跳出来的话,p肯定指向的是head
    	{
    		head=p->next;//删除头结点
    		head->prior=NULL;
    		free(p);
    	}
    	else
    	{
    	if(p->next==NULL)//已经找到最后一个节点了才找到
    	{
    		(p->prior)->next=NULL;
    		free(p);
    	}
    	else //中间某个节点上找到了要删除的节点
    	{
    		p->prior->next=p->next; //语句1  1和2次序很关键,绝对不能颠倒
    		p->next->prior=p->prior;//语句2
    		free(p);
    	}
    	}
    	}
    	else
    	{
    		printf("we can not find the element that you want to find!\n");
    	}
    	return head;
    }
    
    void printDList(DoubleList head)
    {
    	DoubleList p=head;
    	while(p!=NULL)
    	{
    		printf("%d\t",p->element);
    		p=p->next;
    	}
    	printf("\n");
    }
    
    void freeDList(DoubleList head)
    {
    	DoubleList p;
    	if(head==NULL)
    	{
    		return;
    	}
    	while(head!=NULL)
    	{
    		p=head->next;
    		free(head);
    		head=p;
    	}
    }
    
    int main(void)
    {
    	DoubleList head;
    	printf("please input the interge,and create the Doublelist! \n");
    	head=createDList();
    	printf("print the Doublelist you have created!\n");
    	printDList(head);
    	printf("delete the Doublelist!\n");
    	head=delDList(head,0);//delDList()函数有返回值
    	printf("print the Doublelist you have deleted!\n");
    	printDList(head);
    	freeDList(head);
    }

    以上经Cfree5验证通过了的。




    展开全文
  • 双向循环链表的应用

    2016-05-29 12:24:43
    本库文件基于双向循环链表的应用 2.参考Linux内核源码的list.h文件 3.详细说明查看自己总结的文档《Linux中List.h文件的分析和应用》 */ #include #include #include struct list_head { st
    #ifndef DOUBLELINKEDLIST_H
    #define DOUBLELINKEDLIST_H
    
    /*
    	1.本库文件基于双向循环链表的应用
    	2.参考Linux内核源码的list.h文件
    	3.详细说明查看自己总结的文档《Linux中List.h文件的分析和应用》
    
    */
    
    
    #include <stdio.h>
    #include <malloc.h>
    #include <stdlib.h>
    
    struct list_head 
    {
    	struct list_head *next; 
    	struct list_head *prev;
    };
    
    #define LIST_HEAD_INIT(name) { &(name), &(name) }
    
    #define LIST_HEAD(name) \
    	struct list_head name = LIST_HEAD_INIT(name)
    
    static inline void INIT_LIST_HEAD(struct list_head *list)
    {
    	list->next = list;
    	list->prev = list;
    }
    
    
    //插入
    static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
    {
    	next->prev = new;
    	new->next = next;
    	new->prev = prev;
    	prev->next = new;
    }
    
    //适用于堆栈
    static inline void list_add(struct list_head *new, struct list_head *head)
    {
    	__list_add(new, head, head->next);
    }
    
    //适用于队列
    static inline void list_add_tail(struct list_head *new, struct list_head *head)
    {
    	__list_add(new, head->prev, head);
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #endif
    

    展开全文
  • Linux中的双向链表

    2019-05-09 11:27:59
    双向链表也是由节点组成,每个节点是两个指针组成,分别指向直接后继和直接前驱 表头为空,表头的后继节点为"节点10"(数据为10的节点);“节点10"的后继节点是"节点20”(数据为10的节点),“节点20"的前继节点是...
  • 1. Linux中双向链表介绍 Linux双向链表的定义主要涉及到两个文件: include/linux/types.h include/linux/list.h Linux中双向链表的使用思想 它是将双向链表节点嵌套在其它的结构体中;在遍历链表的时候,根据双...
  • 前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法。其中,也会涉及到Linux内核中非常常用的两个经典宏定义offsetof和container_of...
  • linux内核双向链表

    2019-06-02 19:39:06
    前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法。其中,也会涉及到Linux内核中非常常用的两个经典宏定义offsetof和container_of...
  • 链表 队列 映射 二叉树
  • 本文主要涵盖列表(双向链表)的设计及其排序算法的总结。列表是一种典型的动态存储结构。其中的数据,分散为一系列称作节点(node)的单位,节点之间通过指针相互索引和访问。为了引入新节点或删除原有节点,只需在局部...
  • 目录 双向链表list 头文件和命名空间 常用的成员函数 list vs vector 代码使用示例 示例执行结果 总结 双向链表list 相较于数组,链表也是一种非常常见的数据结构,链表的特点主要如下所示: 物理存储上非连续,...
  • Go实现双向链表

    2019-09-20 09:41:48
    本文介绍什么是链表,常见的链表有哪些,然后介绍链表这种数据结构会在哪些地方可以用到,以及 Redis 队列是底层的实现,通过一个小实例来演示 Redis 队列有哪些功能,最后通过 Go 实现一个双向链表。 目录 1、...
  • Python实现双向链表

    2021-06-22 21:58:36
    说明:仅供学习使用,请勿用于非法用途,若有侵权,请联系博主删除 作者:zhu6201976 博客:https://blog.csdn.net/zhu6201976 一、需求 Python实现单向链表,功能如下: 增 头部、中部、尾部插入 删 根据...
  • 双向链表数据结构

    2020-03-16 17:13:48
    文章目录1 双向链表数据结构1.1 链表结构定义1.2 链表操作实现 1 双向链表数据结构 1.1 链表结构定义 对于双向链表的通常做法: 我们可以使用更好的方案: 思考一个问题:已知父结构,如何访问特定结点? 1.2 ...
  • 数组模拟双向链表

    2020-02-27 10:01:00
    用途:多次删除插入操作 准备:l[N],r[N];分别记录该数的左右 操作1.连接两个元素 eg.连接u,v l[v] = u; r[u] = v; 小技巧:虚拟位置0的使用 插入第一个元素1,则r[0] = 1;l[1] = 0; 操作2.插入元素 1.将v插在u的...
  • Linux中双向链表的经典实现 1. Linux中双向链表介绍 Linux双向链表的定义主要涉及到两个文件: include/linux/types.h include/linux/list.h Linux中双向链表的使用思想 它是将双向链表节点嵌套在其它的结构体...
  • afterNodeAccess(Node,V> p),afterNodeInsertion(boolean evict),afterNodeRemoval(Node,V> p)),但我没看到LinkedHashMap是如何实现它在put时候维护双向链表的,有几篇文章提到了但是跟jdk1.8的实现方法还是不同。...
  • 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不能创建任何新的结点,只调整指针的指向。10 / \ 6 14 / \ / \ 4 8 12 16转换成双向链表 4=6=8=10=12=14=16。首先我们定义的二元查找...
  • java双向链表双向链表
  • 一步一步写算法(之双向链表

    万次阅读 多人点赞 2011-10-07 20:03:53
    那么我们今天介绍的双向链表,顾名思义,就是数据本身具备了左边和右边的双向指针。双向链表相比较单向链表,主要有下面几个特点:  (1)在数据结构中具有双向指针  (2)插入数据的时候需要考虑前后的方向的...
  • linux内核-双向链表

    2019-08-09 00:44:10
    虽然名称list_head,但是它既是双向链表的表头,也代表双向链表的节点。 (02). 初始化节点 #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \  struct list_head ...
  • 数据结构中的链表在任何教程里面都是放在最前面讲解,这不仅仅体现它的重要性,而且说明了它的基础性。不说是地基,也能说是根葱,顶梁柱。而且在整个内核当中,无处不在。 记得在上大学的时候,学习数据结构链表,...
  • C双向循环链表

    2019-09-11 21:27:07
    搞开发也有些时间了,想记下些实用的东西,总是一拖在拖,一是每次都懒的不行,二是举的这东西难以上的了厅堂!... 这个链表是仿linux内核做的,只不过简化了很多,只保留了最基本的一些操作!以...
  • 通用双向链表,指的是通过一个通用的数据结构,然后添加特定数据形成有具体用途的链表。这主要涉及到代码复用,在C++中实现非常方便,只需要定义一个双向链表的类,每一个具体业务只需要继承它,然后添加自己的数据...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,121
精华内容 4,448
关键字:

双向链表用途