当前位置: 首页 > news >正文

线性表的链式存储结构——链表

单链表

一.插入和删除结点操作

1.插入s指向的结点

s->next = p->next;
p->next = s;

2.删除结点

q = p->next;   //临时保存被删结点
p->next = q->next;   //从链表中删除结点q
free(q);    //释放结点q的空间

 

二、建立单链表

1.头插法

void CreateListF(LinkNode *&L,ElemType a[],int n)
{
    int i;
    LinkNode *s;
    L = (LinkNode *)malloc(sizeof(LinkNode));
    L->next = NULL;   //创建头结点,其next域设置为NULL
    for(i=0;i<n;i++)
    {
        s = (LinkNode *)malloc(sizeof(LinkNode));
        s->data = a[i];   //循环建立数据结点s
        s->next = L->next;   //将结点s插入到原首结点之前、头结点之后
        L->next = s;
}

2.尾插法

void CreateListR(LinkNode *&L,ElemType a[],int n)
{
    int i;
    LinkNode *s,*r;
    L = (LinkNode *)malloc(sizeof(LinkNode));   //创建头结点
    r = L;   //r始终指向尾结点,初始时指向头结点
    for(i=0;i<n;i++)   //循环建立数据结点
    {
        s = (LinkNode *)malloc(sizeof(LinkNode));
        s->data = a[i];   //创建数据结点s
        r->next = s;   //将结点s插入到结点r之后
        r = s;
    }
    r->next = NULL;   //尾结点的next域置为NULL
}

 

三.线性表基本运算在单链表中的实现

1.初始化线性表

void InitList(LinkNode *&L)
{
    L = (LinkNode *)malloc(sizeof(LinkNode));
    L->next = NULL;   //创建头结点,其next域置为NULL
}

2.销毁线性表

void DestroyList(LinkNode *&L)
{
    LinkNode *pre = L,*p = L->next;   //pre指向结点p的前驱结点
    while(p != NULL)   ;扫描单链表L
    {
        free(pre);   //释放pre结点
        pre = p;   //pre、p同步后移一个结点
        p = pre->next;
    }
    free(pre);   //循环结束时p为NULL,pre指向尾结点,释放它
}

3.判断线性表是否为空表

bool ListEmpty(LinkNode *L)
{
    return(L->next == NULL);
}

4.求线性表的长度

int ListLength(LinkNode *L)
{
    int n=0;
    LinkNode *p = L;   //p指向头结点,n置为0
    while(p->next != NULL)
    {
        n++;
        p = p->next;
     }
     return(n);
}

5.输出线性表

void DispList(LinkNode *L)
{
    LinkNode *p = L->next;
    while(p != NULL)
    {
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
}

6.求线性表中的某个数据元素值

bool GetElem(LinkNode *L,int i,ElemType &e)
{
    int j=0
    LinkNode *p = L;
    if(i <= 0)
        return false;
    while(j<i && p!=NULL)
    {
        j++;
        p = p->next;
    }
    if(p == NULL)
        return false;
    else
    {
        e = p->data;
        return false;
    }
}

7.按元素值查找

int LocateElem(LinkNode *L,ElemType e)
{
    int i=1;
    LinkNode *p = L->next;
    while(p!=NULL && p->data!=e)
    {
        p = p->next;
        i++;
    }
    if(p == NULL)
        return(0);
    else
        return(i);
}

8.插入数据元素

bool ListInsert(LinkNode *&L,int i,ElemType e)
{
    int j=0;
    LinkNode *p = L,*s;
    if(i <= 0)
        return false;
    while(j<i-1 && p!=NULL)
    {
        j++;
        p = p->next;
    }
    if(p == NULL)
        return false;
    else
    {
        s = (LinkNode *)malloc(sizeof(LinkNode));
        s->data = e;
        s->next = p->next;
        p->next = s;
        return true;
    }
}

9.删除数据元素

bool ListDelete(LinkNode *&L,int i,ElemType &e)
{
    int j=0;
    LinkNode *p = L,*q;
    if(i <= 0)
        return false;
    while(j<i-1 && p!=NULL)
    {
        j++;
        p = p->next;
    }
    if(p == NULL)
        return false;
    else
    {
        q = p->next;
        if(q == NULL)
            return false;
        e = q->data;
        p->next= q->next;
        free(q);
        return true;
    }
}

 

四.单链表的应用示例

1.将一个带头结点的单链表L,拆分成两个带头结点的单链表L1和L2,要求L1使用L的头结点

void split(LinkNode *&L,LinkNode *&L1,LinkNode *&L2)
{
    LinkNode *p = L->next,*q,*r1;
    L1 = L;
    r1 = L1;
    L2 = (LinkNode *)malloc(sizeof(LinkNode));
    L2->next = NULL;
    while(p != NULL)
    {
        r1->next = p;   //采用尾插法将p插入L1中
        r1 = p;
        p = p->next;
        q = p->next;
        p->next = L2->next;   //采用头插法将结点p插入L2中
        L2->next = p;
        p = q;
    }
    r1->next = NULL;
}

2.设计一个算法,删除一个单链表L中元素值最大的结点(假设这样的结点唯一)

void delmaxnode(LinkNode *&L)
{
    LinkNode *p=L->next,*pre=L,*maxp=p,*maxpre=pre;
    while(p != NULL)
    {
        if(maxp->data < p->data)   //若找到一个更大的结点
        {
            maxp = p;                      //更新maxp
            maxpre = pre;                //更新maxpre
        }
        pre = p;
        p = p->next;
    }
    maxpre->next = maxp->next;   //删除maxp结点
    free(maxp);   //释放maxp结点
}

3.有一个带头结点的单链表L(至少有一个数据结点),设计一个算法使其元素递增有序排列

void sort(LinkNode *&L)
{
    LinkNode *p,*pre,*q;
    p = L->next->next;
    L->next->next = NULL;
    while(p != NULL)
    {
        q = p->next;
        pre = L;
        while(pre->next!=NULL && pre->next->data < p->data)
            pre = pre->next;
        p->next = pre->next;
        pre->next = p;
        p = q;
}

 

双链表

一.建立双链表

1.头插法:

void CreateListF(DLinkNode *&L,ElemType a[],int n)
{
    DLinkNode *s;
    int i;
    L = (DLinkNode *)malloc(sizeof(DLinkNode));   //创建头结点
    L->prior = L->next = NULL;
    for(i=0;i<n;i++)
    {
        s = (DLinkNode *)malloc(sizeof(DLinkNode));
        s->data = a[i];
        s->next = L->next;   //将s结点插入到头结点之后
        if(L->next != NULL)  //若L存在数据结点,修改L->next的前驱指针
            L->next->prior  = s;
        L->next = s;
        s->prior = L;
    }
}

2.尾插法

void CreateListR(DLinkNode *&L,ElemType a[],int n)
{
    DLinkNode *s,*r;
    int i;
    L = (DLinkNode *)malloc(sizeof(DLinkNode));
    r = L;
    for(i=0;i<n;i++)
    {
        s = (DLinkNode *)malloc(sizeof(DLinkNode));
        s->data = a[i];
        r->next = s;
        s->prior = r;
        r = s;
    }
    r->next = NULL;
}

 

二.线性表基本运算在双链表中的实现

1.插入结点

bool ListInsert(DLinkNode *&L,int i,ElemType e)
{
    int j=0;
    DLinkNode *p = L,*s;
    if(i <= 0)
        return false;
    while(j<i-1 && p!=NULL)
    {
        j++;
        p = p->next;
    }
    if(p == NULL)
        return false;
    else
    {
        s = (DLinkNode *)malloc(sizeof(DLinkNode));
        s->data = e;
        s->next = p->next;
        if(p->next != NULL)
            p->next->prior = s;
        s->prior = p;
        p->next = s;
        return true;
    }
}

2.删除结点

bool ListDelete(DLinkNode *&L,int i,ElemType &e)
{
    int j=0;
    DLinkNode *p=L,*q;
    if(i <= 0)
        return false;
    while(j<i-1 && p!=NULL)
    {
        j++;
        p = p->next;
    }
    if(p == NULL)
        return false;
    else
    {
        q = p->next;
        if(q == NULL)
            return false;
        e = q->data;
        p->next = q->next;
        if(p->next != NULL)
            p->next->prior = p;
        free(q);
        return true;
    }
}
        

三.应用示例

1.有一个带头结点的双链表L,设计一个算法将其所有元素逆置,即第1个元素变为最后一个元素,第2个元素变为倒数第2个元素......最后一个元素变为第1个元素

void reverse(DLinkNode *&L)
{
    DLinkNode *p=L->next,*q;
    L->next = NULL;   //构造只有头结点的双链表L
    while(p != NULL)
    {
        q = p->next;
        p->next = L->next;   //采用头插法将p结点插入到双链表中
        if(L->next != NULL)
            L->next->prior = p;
        L->next = p;   //将新结点作为首结点
        p->next = L;
        p = q;
    }
}

2.有一个带头结点的双链表L(至少有一个数据结点),设计一个算法使其元素递增有序排列

void sort(DLinkNode *&L)
{
    DLinkNode *p,*pre,*q;
    p = L->next->next;
    L->next->next = NULL;  //构造只含一个数据结点的有序表
    while(p != NULL)
    {
        q = p->next;
        pre = L;
        while(pre->next!=NULL && pre->next->data<p->data)
            pre = pre->next;
        p->next = pre->next;
        if(pre->next != NULL)
            pre->next->prior = p;
        pre->next = p;
        p->prior = pre;
        p = q;
    }
}

 

 

循环链表

与单链表的区别在于将它的尾结点next指针域由原来为空改为指向头结点。

转载于:https://www.cnblogs.com/ljlzl/p/10938006.html

相关文章:

  • autocare使用命令
  • 安卓自定义View进阶-Canvas之画布操作 转载
  • Android - 权限
  • 跳石板_牛客网
  • Google浏览器插件
  • 第二阶段冲刺4
  • python篇第10天【For 循环语句】
  • React实战之将数据库返回的时间转换为几分钟前、几小时前、几天前的形式。...
  • 2、CDH组件安装
  • 第一章 Vue介绍
  • awk使用记录
  • (¥1011)-(一千零一拾一元整)输出
  • 第六章 组件 51 组件化和模块化的区别
  • 如何回答——请简述MySQL索引类型
  • WUSTOJ 1307: 校门外的树(Java)
  • CentOS6 编译安装 redis-3.2.3
  • Computed property XXX was assigned to but it has no setter
  • js如何打印object对象
  • js作用域和this的理解
  • MySQL几个简单SQL的优化
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • Node + FFmpeg 实现Canvas动画导出视频
  • npx命令介绍
  • PHP 小技巧
  • Python_网络编程
  • Python语法速览与机器学习开发环境搭建
  • spring + angular 实现导出excel
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 电商搜索引擎的架构设计和性能优化
  • 复杂数据处理
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 开发基于以太坊智能合约的DApp
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • 积累各种好的链接
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • 通过调用文摘列表API获取文摘
  • # C++之functional库用法整理
  • #laravel 通过手动安装依赖PHPExcel#
  • #pragma data_seg 共享数据区(转)
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • (1)SpringCloud 整合Python
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)linux下的时间函数使用
  • (转)我也是一只IT小小鸟
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .net mvc部分视图
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .NET大文件上传知识整理
  • .net反混淆脱壳工具de4dot的使用