C语言线性表之双链表详解

目录
  • 定义
  • 1.删除
  • 2.插入
  • 3.建立
  • 4.查找
  • 总结

定义

链表是通过一组任意的存储单元来存储线性表中的数据元素,每一个结点包含两个域:存放数据元素信息的域称为数据域,存放其后继元素地址的域称为指针域。因此n个元素的线性表通过每个结点的指针域连接成了一个“链条”,称为链表。若此链表的每个结点中包含两个指针域,则被称为双链表

双链表的结点结构定义如下:

typedef struct node
{
    DataType data;
    struct node *llink;
    struct node *rlink;
} DLinkList;

像单链表一样,需要一个类似于“头结点”一样的结点(记为rear),其数据域为空,指针域的llink指针指向表头结点rlink指针指向表尾结点。而表头结点的llink指针指向NULL,表尾结点的rlink指针指向NULL。

1.删除

假设结点p是待删除结点,我们只需让p的前一个结点的rlink指针(p->llink->rlink)指向p的后一个结点(p->rlink),并让p的后一个结点的llink指针(p->rlink->llink)指向p的前一个指针(p->llink),然后释放p所占内存空间,即可完成删除操作。因为这是双链表的删除算法,因此待删除结点在表头或表尾会有略微的区别,但只要抓住核心算法:

p->llink->rlink = p->rlink; p->rlink->llink = p->llink; free(p);

再对表头表尾结点进行特殊处理(改变rear指针的指针域)即可。

双链表删除算法示例如下:

int DeleteDLinkList(DLinkList *rear, DLinkList *p)
/*在双链表删除结点p,成功返回1,否则返回0*/
{
    DLinkList *q = p->rlink, *s = p->llink;/*q指向p的后继,s指向p的前继*/
    if (s!=NULL && q==NULL)/*删除的是最后一个结点*/
    {
        rear->rlink = p->llink;
        p->llink->rlink = p->rlink;
        free(p);
        return 1;
    }
    if (s==NULL && q!=NULL)/*删除的是第一个结点*/
    {
        rear->llink = p->rlink;
        p->rlink->llink = p->llink;
        free(p);
        return 1;
    }
    if (s==NULL & q==NULL)/*双链表只有一个结点*/
    {
        rear->rlink = rear->llink = NULL;
        free(p);
        return 1;
    }
    if (s!=NULL && q!=NULL)
    {
        p->llink->rlink = p->rlink;
        p->rlink->llink = p->llink;
        free(p);
        return 1;
    }
    return 0;
}

2.插入

假设要把结点q插入到结点p与p的后一个结点之间,需要先令q的llink指针(q->llink)和rlink指针(q->rlink)分别指向p和p的后一个结点(p->rlink),再令p的后一个结点的llink指针(p->rlink->llink)指向q,p的rlink指针(p->rlink)指向q。稍加分析可知,若①②③三个步骤顺序错误,则无法完成插入。用代码表示就是:

q->llink = p; q->rlink = p->rlink; p->rlink->llink = q; p->rlink = q;

同样地,若要在表头或表尾插入元素,则紧抓住核心算法稍作改变,并改变rear的指针域即可。

双链表插入算法示例如下:

int Insert(DLinkList *rear, DLinkList *p, DataType x)
{
    DLinkList *q = (DLinkList *)malloc(sizeof(DLinkList));
    if (q == NULL)
        return 0;
    q->data = x;/*数据域赋值*/
    if (p->rlink == NULL)/*在表尾插入元素*/
    {
        rear->rlink = q;
        q->llink = p;
        q->rlink = p->rlink;
        p->rlink = q;
        return 1;
    }
    if (p == rear)/*若p为rear,认为在表头插入元素*/
    {
        q->llink = rear->llink->llink;
        q->rlink = rear->llink;
        rear->llink->llink = q;
        rear->llink = q;
        return 1;
    }
    q->llink = p;
    q->rlink = p->rlink;
    p->rlink->llink = q;
    p->rlink = q;
    return 1;
}

3.建立

利用前面所讲在表尾插入元素的办法,我们可以每建立一个新结点就将其插入到表尾。当刚开始建立双链表时,让rear的llink指针(rear->llink)指向表头结点,并让表头结点指向NULL;当建立结束时,让rear的rlink指针(rear->rlink)指向最后一个结点,即可完成双链表的建立。

DLinkList *CreateDLinkList(){    DLinkList *rear, *p, *q;    rear = (DLinkList *)malloc(sizeof(DLinkList));    p = (DLinkList *)malloc(sizeof(DLinkList));    if (rear==NULL || p==NULL)    {        free(rear);        free(p);        return NULL;    }    DataType x;    scanf(&x);    p->data = x;    rear->llink = p;    p->llink = NULL;    p->rlink = NULL;    scanf(&x);    while (x != flag)/*flag为建立结束的标志*/    {        q = (DLinkList *)malloc(sizeof(DLinkList));        if (q == NULL)        {            DLinkList *pr;            p = rear->llink;            while (p != NULL)            {                pr = p->rlink;                free(p);                p = pr;            }            free(rear);            return NULL;        }        q->data = x;        q->llink = p;        q->rlink = NULL;        p->rlink = q;        scanf(&x);    }    rear->rlink = q;    return rear;}DLinkList *CreateDLinkList()
{
    DLinkList *rear, *p, *q;
    rear = (DLinkList *)malloc(sizeof(DLinkList));
    p = (DLinkList *)malloc(sizeof(DLinkList));
    if (rear==NULL || p==NULL)
    {
        free(rear);
        free(p);
        return NULL;
    }
    DataType x;
    scanf(&x);
    p->data = x;
    rear->llink = p;
    p->llink = NULL;
    p->rlink = NULL;
    scanf(&x);
    while (x != flag)/*flag为建立结束的标志*/
    {
        q = (DLinkList *)malloc(sizeof(DLinkList));
        if (q == NULL)
        {
            DLinkList *pr;
            p = rear->llink;
            while (p != NULL)
            {
                pr = p->rlink;
                free(p);
                p = pr;
            }
            free(rear);
            return NULL;
        }
        q->data = x;
        q->llink = p;
        q->rlink = NULL;
        p->rlink = q;
        scanf(&x);
    }
    rear->rlink = q;
    return rear;
}

4.查找

相对于单链表,双链表的优势是可以实现双向的查找。假设让指针p和指针q分别从表头和表尾向中间遍历双链表的每一个结点,当p==q或p->llink==q时认为已遍历结束。

DLinkList *SearchDLinkList(DLinkList *rear, DataType x)
{
    DLinkList *p = rear->llink, *q = rear->rlink;
    while (p->data!=x && q->data!=x)
    {
        p = p->rlink;
        q = q->llink;
        if (p==q || p->llink==q)
            break;
    }
    if (p->data == x)
        return p;
    else if (q->data == x)
        return q;
    else
        return NULL;
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容

(0)

相关推荐

  • C语言实现循环双链表

    本文实例为大家分享了C语言实现循环双链表的具体代码,供大家参考,具体内容如下 #include<stdio.h> #include<stdlib.h> #include<stdbool.h> typedef int DataType; typedef struct Node { DataType data; // 数据域 struct Node * prior; // 前趋指针 struct Node * next; // 后继指针 }LinkList; LinkLis

  • C语言实现线性表的基本操作详解

    目录 前言 一.实训名称 二.实训目的 三.实训要求 四.实现效果 五.顺序存储代码实现 六.链式存储代码实现 前言 这里使用的工具是DEV C++ 可以借鉴一下 一.实训名称 线性表的基本操作 二.实训目的 1.掌握线性表的基本概念 2.掌握线性表的存储结构(顺序存储与链式存储) 3.掌握线性表的基本操作 三.实训要求 1.线性表可以顺序表也可以用单链表实现,鼓励大家用两种方式实现. 2.创建线性表时,数据从键盘输入整形数据 3.线性表类型定义和或各种操作的实现,可以用教材给出的方法,也可以自

  • C语言的线性表之顺序表你了解吗

    目录 线性表 —— 顺序表 (C语言) 1. 顺序表的储存结构 2. 顺序表的基本操作 2.1 顺序表的插入 2.2 顺序表的查找 2.3 顺序表的删除 总结 线性表 —— 顺序表 (C语言) 概念 线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表中的数据元素,这种表示也称做线性表的顺序储存结构或顺序映像.通常,称这种存储结构的线性表为顺序表 (Sequential List) .其特点是,逻辑上相邻的数据元素,其物理次序也是相邻的. 1. 顺序表的储存结构 #include <st

  • C语言实现的双链表功能完整示例

    本文实例讲述了C语言实现的双链表功能.分享给大家供大家参考,具体如下: Dlist.h #ifndef __DLIST_H__ #define __DLIST_H__ #include<cstdio> #include<malloc.h> #include<assert.h> typedef int ElemType; typedef struct Node { ElemType data; struct Node *prio; struct Node *next; }

  • 一起来看看C语言线性表的线性链表

    目录 定义 1.插入 2.建立线性链表 1)头插法 2)尾插法 3.删除 4.查找 5.求线性链表的表长 总结 定义 链表是通过一组任意的存储单元来存储线性表中的数据元素,每一个结点包含两个域:存放数据元素信息的域称为数据域,存放其后继元素地址的域称为指针域.因此n个元素的线性表通过每个结点的指针域连接成了一个“链条”,称为链表.若此链表的每个结点中只包含一个指针域,则被称为线性链表或单链表. 线性表的链式存储结构,它不需要用地址连续的存储单元来实现,因为它不要求逻辑上相邻的两个数据元素物理位置

  • C语言线性表之双链表详解

    目录 定义 1.删除 2.插入 3.建立 4.查找 总结 定义 链表是通过一组任意的存储单元来存储线性表中的数据元素,每一个结点包含两个域:存放数据元素信息的域称为数据域,存放其后继元素地址的域称为指针域.因此n个元素的线性表通过每个结点的指针域连接成了一个“链条”,称为链表.若此链表的每个结点中包含两个指针域,则被称为双链表. 双链表的结点结构定义如下: typedef struct node { DataType data; struct node *llink; struct node *

  • C语言线性表顺序存储结构实例详解

    C语言线性表顺序存储结构实例详解 1. 什么是顺序存储结构? 用一段地址连续的存储单元依次存储线性表的数据元素. 2.线性表的顺序存储结构 #include<stdio.h> #include<stdlib.h> #define Max 80 //存储空间初始分配量 #define Increment 10 //存储空间分配增量 typedef struct { int *elem; // 存储空间基地址,此处为int型,视情况而定 int length; // 元素表当前长度 i

  • java 线性表接口的实例详解

    java 线性表接口的实例详解 前言: 线性表是其组成元素间具有线性关系的一种线性结构,对线性表的基本操作主要有插入.删除.查找.替换等,这些操作可以在线性表的任何位置进行.线性表可以采用顺序存储结构和链式存储结构表示. 本接口的类属于dataStructure包的linearList子包.线性表接口LList声明如下,描述线性表的取值.置值.插入.删除等基本操作. package dataStructure.linearList; public interface LList<E> { bo

  • Python线性表种的单链表详解

    目录 1. 线性表简介 2. 数组 3. 单向链表 设计链表的实现 链表与顺序表的对比 1. 线性表简介 线性表是一种线性结构,它是由零个或多个数据元素构成的有限序列.线性表的特征是在一个序列中,除了头尾元素,每个元素都有且只有一个直接前驱,有且只有一个直接后继,而序列头元素没有直接前驱,序列尾元素没有直接后继. 数据结构中常见的线性结构有数组.单链表.双链表.循环链表等.线性表中的元素为某种相同的抽象数据类型.可以是C语言的内置类型或结构体,也可以是C++自定义类型. 2. 数组 数组在实际的

  • C语言线性表的链式表示及实现详解

    目录 前言 代码实现 1. 单链表的结点构造 2. 构造一个空的头结点 3. 对线性表进行赋值 4.对线性表进行销毁 5.对线性表进行重置 6.判断线性表是否为空 7.获取线性表的长度 8.获取线性表某一位置对应的元素 9.在线性表某一位置插入元素 10.删除线性表某一位置的元素 11.求线性表某一元素的前驱 12.求线性表某一元素的后继 13.打印线性表 运行结果演示 源码 前言 线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,而线性表的链式存储特点则是用一组任意的存储

  • C语言实现顺序表的全操作详解

    目录 线性表 顺序表 顺序表接口实现 1.顺序表初始化 2.顺序表空间增容 3.顺序表打印 4.尾插数据 5.尾删数据 6.头插数据 7.头删数据 8.在pos下标处插入数据 9.删除pos下标处数据 10.数据查找 11.顺序表摧毁 线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列.线性表是一种在实际中广泛使用的数据结构,常见的线性表有:顺序表.链表.栈.队列.字符串等. 线性表在逻辑上是线性结构,也就是连续的一条直线.但在物理结构上并不一定是连续的,线性表在物理

  • C语言数据结构之单向链表详解分析

    链表的概念:链表是一种动态存储分布的数据结构,由若干个同一结构类型的结点依次串连而成. 链表分为单向链表和双向链表. 链表变量一般用指针head表示,用来存放链表首结点的地址. 每个结点由数据部分和下一个结点的地址部分组成,即每个结点都指向下一个结点.最后一个结点称为表尾,其下一个结点的地址部分的值为NULL(表示为空地址). 特别注意:链表中的各个结点在内存中是可以不连续存放的,具体存放位置由系统分配. 例如:int *ptr ; 因此不可以用ptr++的方式来寻找下一个结点. 使用链表的优点

  • C语言链表与单链表详解

    链表是什么及链表的优势 链表是一种介于数组的另外一种数据结构: 我们知道数组可以存放很多的元素,这些元素都是呈线性排列,也就是一个挨着一个连续存放 但是当元素足够多时,还能继续正常的存放吗? 事实上的不可以的,虽然系统的内存足够大,但是这些内存不都是连续的,这就导致会出现没有足够的空间去存储这些元素. 其次就是数组的大小需要你去申请,如果你申请的空间足够大,就会导致内存的浪费 而链表就很好的解决了这两个问题 链表的组成 链表的作用就是相当与数组一样,储存你数据的 但又不同于数组,链表把每一个游离

  • C语言实现无头单链表详解

    目录 链表的结构体描述(节点) 再定义一个结构体(链表) 断言处理 & 判空处理 创建链表 创建节点 头插法 打印链表 尾插法 指定位置插入 头删法 尾删法 指定位置删除 查找链表 删除所有指定相同的元素 总结 再封装的方式,用 c++ 的思想做无头链表 链表的结构体描述(节点) #include <stdio.h> #include <stdlib.h> #include <assert.h> typedef int DataType; //节点 typede

  • C语言线性表全面梳理操作方法

    线性表:零个或多个数据元素的有限序列 强调几点: 首先它是一个序列.也就是说,元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他都有一个前驱和后继. 其次线性表强调是有限的. 线性表有两种物理结构,第一种是顺序存储结构,另一种是链式存储结构. 线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素.用c语言的一维数组来实现顺序存储结构. 线性表顺序存储结构的优缺点 优点:可以快速地读取表中任一位置的元素 无需为表示表中元素之间的逻辑关系而增加额

随机推荐