【第22期】观点:IT 行业加班,到底有没有价值?

五、线性表(2)

原创 2016年08月30日 15:13:11

1、线性表链式存储结构

我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称为指针或链。这两部分信息组成数据元素称为存储映像,称为结点(Node)。
单链表:这里写图片描述
单链表的读取
获得链表第i个数据的算法思路:

  • 声明一个结点p指向链表第一个结点,初始化j从1开始;
  • 当j < i 时,就遍历链表,让p的指针向后移动,不断指向下一结点,j+1;
  • 若到链表末尾p为空,则说明第i个元素不存在;
  • 否则查找成功,返回结点p的数据。
status getelem(linklist L,int i,elemtype *e)
{
    int j;
    linklist p;
    p=L->next;
    j=1;
    while(p&&j<i)
    {
        p=p->next;
        ++j;
    }
    if(!p||j>i)
    {
        return error;
    }
    *e=p->data;
    return OK;
}

单链表的插入
单链表第i个数据插入结点的算法思路:

  • 声明一个结点p指向链表第一个结点,初始化j从1开始;
  • 当j < i 时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1;
  • 若到链表末尾p为空,则说明第i个元素不存在;
  • 否则查找成功,在系统中生成一个空结点s;
  • 将数据元素e赋值给s->data;
  • 单链表的插入两个标准语句;
    s->next=p->next;
    p->next=s;
  • 返回成功。
status listinsert(linklist *L,int i,elemtype e)
{
    int j;
    linklist p,s;
    p=*L;
    j=1;
    while(p&&j<i)//用于寻找第i个结点
    {
        p=p->next;
        j++;
    }
    if(!P||j>i)
    {
        return error;
    }
    s(linklist)malloc(sizeof(node));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return OK;
}

单链表的删除
如图,上为单链表的插入,下为删除:
这里写图片描述
单链表第i个数据删除结点的算法思路:

  • 声明一个结点p指向链表第一个结点,初始化j从1开始;
  • 当j < i 时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1;
  • 若到链表末尾p为空,则说明第i个元素不存在;
  • 否则查找成功,将欲删除结点p->next赋值给q;
  • 单链表的删除标准语句p->next=q->next;
  • 将q结点中的数据赋值给e,作为返回;
  • 释放q结点。
status listdelete(linklist *L,int i,elemtype *e
{
    int j;
    linklist p,q;
    p=*L;
    j=1;
    while(o->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;
}

单链表的整表创建

  • 对于顺序存储结构的线性表的整表创建,我们可以用数组的初始化来直观理解。
  • 而单链表和顺序存储结构不一样,它的数据可以是分散在内存各个角落,它的增长也是动态的。
  • 对于每个链表来说,它所占用空间的大小和位置是不需要预先分配划定的,可以根据系统的情况和实际的需求即时生成。

    单链表整表创建的算法思路:

  • 声明一结点p和计数器变量i;

  • 初始化一空链表L;
  • 让L的头结点的指针指向NULL,即建立一个带头结点的单链表;
  • 循环实现后继结点的赋值和插入。

头插法建立单链表
头插法从一个空表开始,生成新结点,读取数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头上,直到结束为止。简单来说就是把新加进的元素放在表头后的第一个位置。

void createlisthead(linklst *L,int n)
{
    linklist p;
    int i;                          
    srand(time(0));//初始化随机数种子

    *L(linklist)malloc(sizeof(Node));
    (*L)->next=NULL;
    for(i=0;i<n;i++)
    {
        p=(linklist)malloc(sizeof(Node));//生成新结点
        p->data=rand()%100+1;
        p->next=(*L)->next;
        (*L)->next=p;
    }
}

尾插法建立单链表

void createlisttail(linklist *L,int n)
{
    linklist p,r;
    int i;
    srand(time(0));
    *L=(linklist)malloc(sizeof(Node));
    r=*L;
    for(i=0;i<n;i++)
    {
        p=(Node*)malloc(sizeof(Node));
        p->data=rand()%100+1;
        r->next=p;
        r=p;
    }
    r-<next=NULL;
}

单链表的整表删除
单链表整表删除的算法思路:

  • 声明结点p和q;
  • 将第一个结点赋值给p,下一结点赋值给q;
  • 循环执行释放p和将q赋值给p的操作。
status clearlist(linklist *L)
    {
        linklist p,q;
        p=(*L)->next;
        while(p)
        {
            q=p->next;
            free(p);
            p=q;
        }
        (*L)->next=NULL;
        return OK;
    }

2、单链表结构与顺序存储结构优缺点

1、存储分配方式:
- 顺序存储结构用一段连续的存储单元依次存储线性表的数据元素。
- 单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素。
2、 时间性能:
- 查找:
顺序存储结构O(1)
单链表O(n)
- 插入和删除
顺序存储结构需要平均移动表长一半的元素,时间为O(n)
单链表在计算出某位置的指针后,插入和删除时间仅为O(1)
3、空间性能:
- 顺序存储结构需要分配内存存储空间,分大了,容易造成空间浪费,分小了,容易发生溢出。
- 单链表不需要分配存储空间,只要有就可以分配,元素个数也不受限制。

结论
若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。
若需要频繁插入和删除时,宜采用单链表结构。

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

数组实现的线性表的基本操作2[C语言]

#include #include #define MAXSIZE 10 // 存储空间最大存储10个元素 #define SUCCESS 1 #define ERROR 0typedef i...

C语言数据结构实战(一)顺序表的插入与删除

今天学习了思成老师的数据结构实战教程 写了一个顺序表 插入和删除的操作 把源码共享给大家 一共包括list.c stu.h main.c list.h   .h文件是头文件 需要引入 具体的功能我都已经在代码中写明了  list.h代码如下: //线性表的定义在头文件中实现 #ifndef _LIST_H #define _LIST_H #define _LIST_INIT

2-5-归并链式存储的单链表-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版

严蔚敏吴伟民版《数据结构》课本源码第2章线性表第5节归并链式存储的单链表。

数据结构系列一: 顺序表和链表(线性结构)

顺序表和链表都属于线性结构,那么首先需要明白什么是线性结构。 线性结构的特点: 1)同一线性表中元素具有相同特性(元素的“均一性”)。 2)相邻数据元素之间存在序偶关系。 (即,除第一个元素外,其他每一个元素有且仅有一个直接前驱;除最后一个元素外,其他每一个元素有且仅有一个直接后继。) 3)元素在线性表中的“下标”唯一地确定该元素在表中的相对位置(元素的“索引性”
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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