大话数据结构:线性表(2)

原创 2016年05月30日 21:04:10

1.线性表的链式存储结构

1.1 顺序存储结构不足的解决办法

线性表的顺序存储结构最大的缺点是插入和删除时需要移动大量数据,这显然就需要消耗时间。本节讨论的链式存储结构可以很好滴解决这个问题。

线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这些存储单元可以使连续的,也可以是不连续的。这就意味着,这些数据元素可以存在内存未被占用的任意位置。
以前的顺序结构中,每个数据元素只需要存数据元素的信息就可以了。现在链式结构中,除了要存数据元素信息外,还要存储它的后继元素的存储地址。
因此,为了表示每一个数据元素a(i)与其直接后继数据元素a(i+1)之间的逻辑关系。对数据a(1)来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。我们把存储数据元素信息的域称为数据域;把存储直接后继位置的域称为指针域。指针域中存储的信息称为指针或链。这两部分信息组成元素a(i)的存储映像,称为结点。如果每个结点只包含一个指针域,叫做单链表。单链表正是通过每个节点的指针域将线性表的数据元素按其逻辑次序连接在一起,如图所示:

对于线性表来说,总要有头有尾,链表也不例外。我们把链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须是从头指针开始进行了。之后的每一个结点,其实就是上一个的后继指针指向的位置。最后有意义的是讨论最后一个结点的指针指向问题,暂时规定,线性链表的最后一个结点指针为“空”(NULL)

有时,我们为了更加方便地对链表进行操作,会在单链表的第一个结点前附设一个结点,称为头结点。头结点的数据域可以不存储任何信息,头结点的指针域存储指向第一个结点的指针,如图所示:

2.单链表操作

2.1 单链表的读取

在线性表的顺序存储结构中,我么要计算任意一个元素的存储位置时容易的。但是在单链表中,由于第i个元素到底在哪?没办法一开始就知道,必须从头开始找。
获得链表第i个数据的算法思路:
(1)声明一个结点p指向链表第一个结点,初始化j从1开始;
(2)当j<i时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1;
(3)若到链表末尾p为空,则说明第i个元素不存在;
(4)否则查找成功,返回结点p的数据。
代码实现如下:
Status GetElem( LinkList* L, int i, ElemType* e)
{
      int j;
      LinkList p; //声明一节点p
      p = L->next; //让p指向链表L的第一个节点
      j = 1;
      while ( p && j<i)  //p不为空 或者计数器j还没有等于i时,循环继续
      {
             p = p->next; //让p指向下一个结点
             ++j;
       }
       if (!p || j>1i)
              return ERROR;
       *e = p->data;
       return OK;
}
说白了,就是从头开始找,知道第i个元素为止。由于这个算法的时间复杂度取决于i的位置,当i=1时,则不需要遍历,第一个就取出数据了,而当i = n时,则遍历n-1次就可以了,因此最坏情况的时间复杂度是O(n)。
由于单链表的结构中没有定义表长,所以不能事先知道要循环多少次,因此也就不方便使用for来控制循环。其主要核心思想就是“工作指针后移”。

2.2 单链表的元素插入

单链表的元素插入用不着惊到其他结点,只需要让s->next和p->next的指针做一点改变即可。

s->next = p->next;
p->next =s;
单链表第i个数据插入节点的算法思路:
(1)声明一结点p指向链表第一个结点,初始化j从1开始;
(2)当j<i时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1;
(3)若到链表末尾p为空,则说明第i个元素不存在;
(4)否则查找成功,在系统中生成一个空节点s;
(5)将数据元素e赋值给s->data;
(6)单链表的插入标准语句s->next=p->next;p->next = s;
(7)返回成功。
实现代码算法如下:
Status ListInsert ( LinkList *L, int i, ElemType e)
{
       int j;
       LinkList p,s;
       p = *L;'
       j = 1;
       while( p && j<i)
       {
            p = p->next;
            ++j;
       }
       if ( !p || j>1)
             return ERROR;
       s = (LinkList)malloc(sizeof(Node));
        s->data = e;
        s->next = p->next;
        p->next = s;
        return OK;
}

2.3 单链表的元素删除
设存储元素a(i)的结点为q,要实现将节点q删除单链表操作,其实就是将他的前几结点的指针绕过,指向它的后继结点即可,如图所示:

这里需要做的只有一步,p->next = p->next->next,用q来取代p->next,删除语句可以写成:
q=p->next;
p->next = q->next;
单链表第i个数据删除节点的算法思路:
(1)声明一个结点p指向链表第一个结点,初始化j从1开始;
(2)当j小于i时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;
(3)若到链表末尾p为空,则说明第i个元素不存在;
(4)否则查找成功,将预删除的结点p->next赋值给q;
(5)单链表的删除标准语句p->next=q->next;
(6)将q结点中的数据赋值给e,作为返回;
(7)释放q结点;
(8)返回成功。
实现代码算法如下:
Status ListDelete( LinkList* L, int i, ElemType* e)
{
      int j;
      LinkList p,q;
      p = *L;
      j = 1;
      while( p->next || j<i )
      {
            p = p->next;
            ++j;
       }
       if ( !(p->next) || j>i)
             return ERROR;
       q=p->next;
       p->next=q->next;
       *e = q->data;
       free(q);
       return OK;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

大话数据结构之三:线性表

1.定义: 线性表表示0个或者多个数据元素的有限序列 线性表的特性有: 除第一个元素外,每一个元素均有一个直接前驱 出最后一个元素外,每一个元素均有一个直接后继 2.线性表抽象数据类型 ...
  • longshengguoji
  • longshengguoji
  • 2013年06月27日 23:38
  • 3482

数据结构之线性表代码实现顺序存储,链式存储,静态链表(选自大话数据结构)

一,线性表顺序存储 #include #include #include #include #include #include #include #define ...
  • acm_hmj
  • acm_hmj
  • 2016年04月07日 17:50
  • 1326

大话数据结构与算法:基础篇

1.数据结构的重要性         数据结构是计算机软件相关专业的基础课程,几乎可以说,要想从事编程工作,无论是否是科班出身(比如我,标准的非科班人员,我是学医的,哈哈)都不可以绕过数据结构与算法...
  • shenziheng1
  • shenziheng1
  • 2016年05月26日 13:52
  • 1258

《大话数据结构》读书笔记(一)

学科起源数据结构是一门研究非数值计算的程序设计问题中的操作对象,以及它们之间的关系和操作等相关问题的学科。 程序设计的本质是对确定的问题选择一种好的结构,加上设计一种好的算法, 程序设计 = 数...
  • gao_yu_long
  • gao_yu_long
  • 2017年06月06日 15:25
  • 203

[数据结构]程杰《大话数据结构》单链表代码

#include "stdio.h" #include "string.h" #include "ctype.h" #include "stdlib.h" #include "math.h" #inc...
  • ilikeprograming
  • ilikeprograming
  • 2013年10月01日 23:56
  • 2019

大话数据结构小结1

由于图片看不了,大家可以看这个百度云笔记,我看完大话数据结构整理的,里面有些内容我还不太明白,等过段时间还需要仔细回顾回顾。点击打开链接 一.数据及数据结构的基本概念 数据结构...
  • aiyingwo
  • aiyingwo
  • 2015年11月19日 11:02
  • 695

大话数据结构十一:字符串的模式匹配(KMP算法)

1. KMP算法简介: kmp算法是一种改进的字符串匹配算法,相比朴素算法,KMP算法预先计算出了一个哈希表,用来指导在匹配过程中匹配失败后尝试下次匹配的起始位置,以此避免重复的读入和匹配过程。这个...
  • zdp072
  • zdp072
  • 2013年10月27日 09:14
  • 2730

大话数据结构——图

图(Graph)是由定点的又穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。一、各种图的定义图按是否有方向分可分为有向图和无向...
  • u013159040
  • u013159040
  • 2016年06月14日 16:31
  • 578

大话数据结构(六)——队列的两种java实现方式

记得说桟的时候用了羽毛球的例子:羽毛球盒只有一个端口,取出和放入都得从这个口进行,并且放入和取出的原则遵循“后入先出”的原则。而队列与桟的原则相反,桟的原理就好比这个羽毛球盒子是两头开的,放入的时候从...
  • u013393958
  • u013393958
  • 2017年05月27日 18:46
  • 299

大话数据结构——树

一、树的定义**树(Tree)是n(n>=0)个结点的有限集。**n=0又称为空树。在任意一课非空的树中:(1)有且仅有一个特定的称为跟(Root)的结点;(2)当n>1时,其余结点可分为m(m>0)...
  • u013159040
  • u013159040
  • 2016年06月13日 17:51
  • 6498
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:大话数据结构:线性表(2)
举报原因:
原因补充:

(最多只允许输入30个字)