数据结构之线性表的链式存储结构

摘要:
用这种方法存储的线性表简称线性链表。该方法是将新结点插入到当前链表的表尾,使其成为当前链表的尾结点。若有,则返回首次找到的值为key的结点的存储位置;否则返回NULL。最后释放结点ai的空间,将其归还给“存储池”。

一、基本概念

链式存储 :用一组任意的存储单元存储线性表中的数据元素。用这种方法存储的线性表简称线性链表。存储链表中结点的一组任意的存储单元可以

是连续的,也可以是不连续的,甚至是零散分布在内存中的任意位置上的。

为了正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其直接后继结点的地址(或位置),称为指针(pointer)或链(link),这两部分

组成了链表中的结点结构,如下图所示。

数据结构之线性表的链式存储结构第1张

data :数据域,存放结点的值。next :指针域,存放结点的直接后继的地址。

二、单链表

每一个结只包含一个指针域的链表,称为单链表。

为操作方便,总是在链表的第一个结点之前附设一个头结点(头指针)head指向第一个结点。头结点的数据域可以不存储任何信息(或链表长度等信息)。

单链表是由表头唯一确定,因此单链表可以用头指针的名字来命名。 例如、线性表L=(bat,cat,eat,fat,hat)。其带头结点的存储方式如下:

数据结构之线性表的链式存储结构第2张

(1)节点的描述与实现

C语言中用带指针的结构体类型来描述

typedef struct Lnode

{  ElemType data; /*数据域,保存结点的值 */

struct Lnode *next; /*指针域*/

}LNode; /*结点的类型 */

(2)节点的实现

结点是通过动态分配和释放来的实现,即需要时分配,不需要时释放。实现时是分别使用C语言提供的标准函数:malloc() ,realloc(),sizeof() ,free() 。

动态分配 p=(LNode*)malloc(sizeof(LNode)); 函数malloc分配了一个类型为LNode的结点变量的空间,并将其首地址放入指针变量p中。

动态释放 free(p) ; 系统回收由指针变量p所指向的内存区。P必须是最近一次调用malloc函数时的返回值。

三、单链表的基本操作

1、单链表的创建

假设线性表中结点的数据类型是整型,以32767作为结束标志。动态地建立单链表的常用方法有如下两种:头插入法,尾插入法。

(1)头插入法建表

从一个空表开始,重复读入数据,生成新结点,将读入数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头上,直到读入结束标志为止。

即每次插入的结点都作为链表的第一个结点。

LNode *create_LinkList(void)

/* 头插入法创建单链表,链表的头结点head作为返回值 */

{ int data ;

LNode *head, *p;

head= (LNode *) malloc( sizeof(LNode));

head->next=NULL; /* 创建链表的表头结点head */

while (1) {

scanf(“%d”, &data) ;

if (data==32767) break ;

p= (LNode *)malloc(sizeof(LNode));

p–>data=data; /* 数据域赋值 */

p–>next=head–>next ;

head–>next=p ; /* 钩链,新创建的结点总是作为第一个结点 */

}

return (head);

}

(2)尾插入法建表

头插入法建立链表虽然算法简单,但生成的链表中结点的次序和输入的顺序相反。若希望二者次序一致,可采用尾插法建表。该方法是将新结点插入到

当前链表的表尾,使其成为当前链表的尾结点。

LNode *create_LinkList(void)

/* 尾插入法创建单链表,链表的头结点head作为返回值 */

{ int data ;

LNode *head, *p, *q;

head=p=(LNode *)malloc(sizeof(LNode));

p->next=NULL; /* 创建单链表的表头结点head */

while (1) {

scanf(“%d”,& data);

if (data==32767) break ;

q= (LNode *)malloc(sizeof(LNode));

q–>data=data; /* 数据域赋值 */

q–>next=p–>next; p–>next=q; p=q ;

/*钩链,新创建的结点总是作为最后一个结点*/

}

return (head);

}

2、单链表的查找

按值查找是在链表中,查找是否有结点值等于给定值key的结点? 若有,则返回首次找到的值为key的结点的存储位置;否则返回NULL。查找时从

开始结点出发,沿链表逐个将结点的值和给定值key作比较。

LNode *Locate_Node(LNode *L,int key)

/* 在以L为头结点的单链表中查找值为key的第一个结点 */

{ LNode *p=L–>next;

while ( p!=NULL&& p–>data!=key) p=p–>next;

if (p–>data==key) return p;

else {

printf(“所要查找的结点不存在!! ”);

retutn(NULL);

}

}

3、单链表的插入

插入运算是将值为e的新结点插入到表的第i个结点的位置上,即插入到ai-1与ai之间。因此,必须首先找到ai-1所在的结点p,然后生成一个数据域为e

的新结点q,q结点作为p的直接后继结点。

void Insert_LNode(LNode *L,int i,ElemType e)

/* 在以L为头结点的单链表的第i个位置插入值为e的结点 */

{ int j=0; LNode *p,*q;

p=L–>next ;

while ( p!=NULL&& j<i-1)

{p=p–>next; j++; }

if (j!=i-1) printf(“i太大或i为0!! ”);

else {

q=(LNode *)malloc(sizeof(LNode));

q–>data=e;

q–>next=p–>next;

p–>next=q;

}

}

4、单链表的删除

(1)按序号删除

删除单链表中的第i个结点。 为了删除第i个结点ai,必须找到结点的存储地址。该存储地址是在其直接前趋结点ai-1的next域中,因此,必须首先找到

ai-1的存储位置p,然后令p–>next指向ai的直接后继结点,即把ai从链上摘下。最后释放结点ai的空间,将其归还给“存储池”。

void Delete_LinkList(LNode *L, int i)

/* 删除以L为头结点的单链表中的第i个结点 */

{ int j=1; LNode *p,*q; p=L;

q=L->next;

while ( p->next!=NULL&& j<i)

{ p=q; q=q–>next; j++; }

if (j!=i) printf(“i太大或i为0!! ”);

else {

p–>next=q–>next;

free(q);

}

}

(2)按值删除

删除单链表中值为key的第一个结点。 与按值查找相类似,首先要查找值为key的结点是否存在? 若存在,则删除;否则返回NULL。

void Delete_LinkList(LNode *L,int key)

/* 删除以L为头结点的单链表中值为key的第一个结点 */

{ LNode *p=L,

*q=L–>next;

while ( q!=NULL&& q–>data!=key)

{ p=q; q=q–>next; }

if (q–>data==key)

{ p->next=q->next; free(q); }

else

printf(“所要删除的结点不存在!! ”);

}

免责声明:文章转载自《数据结构之线性表的链式存储结构》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇HAProxy安装配置用于TCP的负载均衡fragment 中利用spinner实现省市联动下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C++的标准模板库STL中实现的数据结构之顺序表vector的分析与使用

摘要本文主要借助对C++的标准模板库STL中实现的数据结构的学习和使用来加深对数据结构的理解,即联系数据结构的理论分析和具体的应用实现(STL),本文是系列总结的第一篇,主要针对线性表中的顺序表(动态数组)STL vector进行分析和总结。 引言由于前段时间对台大的机器学习基石和技法课程进行了学习,发现在具体的实现中常常涉及到各种类型的数据结构,比...

C# 求链表 list 中 属性的 最大值 最小值

获取链表List中对象属性最大值最小值(Max,Min)的方法: 1.创建一个类,类中有一个属性A 1 /// <summary> 2 ///用于测试属性的类 3 /// </summary> 4 public classListTest 5 { 6 private inta; 7...

fatfs源码阅读

使用fatfs文件的第一步,就是调用F_mount函数注册一个工作空间。   F_mount函数的原型如下:     第一个参数根据网上大神的答复,是外设类型,如果是sd卡就是0,flash等等其他的外设就是其他得数,据说有定义,不过我没找到。 第二个参数FATFS指针就是工作空间的指针,个人感觉有点lwip网卡数据结构的感觉。     FATFS数据结构...

CodeFactory VS2008插件使用简介

  CodeFactory是一款基于VS2008的代码生成插件,插件结合NVelocity模板引擎使用户方便地实现基于:c#、xml和HTML等代码或文件生成操作。新版本的CodeFactory插件除了原来的文件插入代码功能外,还添加了直接生成项目文件功能。以下介绍CodeFactory的配置、文件代码生成和项目文件生成等功能。 n    配置只要直文件解...

HttpClient(四)-- 使用代理IP 和 超时设置

1.代理IP的用处:   在爬取网页的时候,有的目标站点有反爬虫机制,对于频繁访问站点以及规则性访问站点的行为,会采集屏蔽IP措施。这时候,就可以使用代理IP,屏蔽一个就换一个IP。 2.代理IP分类:   代理IP的话 也分几种: 透明代理、匿名代理、混淆代理、高匿代理,一般使用高匿代理。 3.使用 RequestConfig.custom().setP...

判断栈和堆的生长方向

如何判断栈的增长方向? 对于一个用惯了i386系列机器的人来说,这似乎是一个无聊的问题,因为栈就是从高地址向低地址增长。不过,显然这不是这个问题的目的,既然把这个问题拿出来,问的就不只是i386系列的机器,跨硬件平台是这个问题的首先要考虑到的因素。 在一个物质极大丰富的年代,除非无路可退,否则我们坚决不会使用汇编去解决问题,而对于这种有系统编程味道的问题,...