第8课-线性表的链式存储结构

顺序表的最大问题是插入和删除需要移动大量的元素! 如何解决?

学生A:在线性表数据元素之间空出位置,为以后插入使用。

学生B:这样不行!中间无论空多少都有可能用完 !

学生A:那不是无解了嘛!

学生B:我觉得让每个元素都知道他的下个元素就行了,哪有空插哪。

1. 链式存储结构

为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示其直接后继的信息。

l  链式存储逻辑结构

n个结点链接成一个链式线性表的结构叫做链表,当每个结点中只包含一个指针域时,叫做单链表。

l  表头结点

链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息。

l  数据结点

链表中代表数据元素的结点,包含指向下一个数据元素的指针和数据元素的信息。

l  尾结点

链表中的最后一个数据结点,其下一元素指针为空,表示无后继。

2. C语言中的描述

在C语言中可以用结构体来定义链表中的指针域。

链表中的表头结点也可以用结构体实现。

typedef struct _tag_LinkList

{

LinkListNode header;

int length;

}TLinkList;    //头结点定义

typedef struct _tag_LinkListNode LinkListNode

struct _tag_LinkListNode

{

LinkListNode* next;

int length;

}TLinkList;    //结点指针域定义

struct Value

{

LinkListNode header;

int v;

};             //数据元素定义实例

3. 获取第pos个元素操作

(1)      判断线性表是否合法。

(2)      判断位置是否合法。

(3)      由表头开始通过next指针移动pos次后,当前元素的next指针即指向要获取的元素。

LinkListNode* current = (LinklistNode*)List;

for(i=0; i<pos; i++)

{

current = crrrent->next;

}

ret = current->next;

4. 插入元素到位置pos的算法

(1)      判断线性表是否合法。

(2)      判断插入位置是否合法。

(3)      由表头开始通过next指针移动pos次后,当前元素的next指针即指向要插入的位置。

(4)      将新元素插入。

(5)      线性表长度加1。

LinkListNode* current = (LinklistNode*)List;

for(i=0; (i < pos) && (current->next != NULL); i++)

{

current = current->next;

}

node->next = current->next;

current->next = node;

sList->length++;

5. 删除第pos个元素的算法

(1)       判断线性表是否合法。

(2)       判断插入位置是否合法。

(3)       获取第pos个元素。

(4)       将第pos个元素从链表中删除。

(5)       线性表长度减1。

TLinkList* sList = (TLinkList*)list;

LinkListNode* ret = NULL;

int i = 0;

if((sList != NULL) && (0 <=pos) && (pos < sList->length))

{

LinkListNode* current = (LinkListNode*)list;

for(i=0; i<pos; i++)

{

current = current->next;

}

ret = current->next;

current->next = ret->next;

sList->length--;

}

6. 手把手编程

LinkList.h

#ifndef _LINKLIST_H_

#define _LINKLIST_H_

typedef void LinkList;

typedef struct _tag_LinkListNode LinkListNode;

struct _tag_LinkListNode

{

LinkListNode* next;

};

LinkList* LinkList_Create();

void LinkList_Destroy(LinkList* list);

void LinkList_Clear(LinkList* list);

int LinkList_Length(LinkList* list);

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);

LinkListNode* LinkList_Get(LinkList* list, int pos);

LinkListNode* LinkList_Delete(LinkList* list, int pos);

#endif

LinkList.c

#include <stdio.h>

#include <malloc.h>

#include "LinkList.h"

typedef struct _tag_LinkList

{

LinkListNode header;

int length;

} TLinkList;

LinkList* LinkList_Create() // O(1)

{

TLinkList* ret = (TLinkList*)malloc(sizeof(TLinkList));

if( ret != NULL )

{

ret->length = 0;

ret->header.next = NULL;

}

return ret;

}

void LinkList_Destroy(LinkList* list) // O(1)

{

free(list);

}

void LinkList_Clear(LinkList* list) // O(1)

{

TLinkList* sList = (TLinkList*)list;

if( sList != NULL )

{

sList->length = 0;

sList->header.next = NULL;

}

}

int LinkList_Length(LinkList* list) // O(1)

{

TLinkList* sList = (TLinkList*)list;

int ret = -1;

if( sList != NULL )

{

ret = sList->length;

}

return ret;

}

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) // O(n)

{

TLinkList* sList = (TLinkList*)list;

int ret = (sList != NULL) && (pos >= 0) && (node != NULL);

int i = 0;

if( ret )

{

LinkListNode* current = (LinkListNode*)sList;

for(i=0; (i<pos) && (current->next != NULL); i++)

{

current = current->next;

}

node->next = current->next;

current->next = node;

sList->length++;

}

return ret;

}

LinkListNode* LinkList_Get(LinkList* list, int pos) // O(n)

{

TLinkList* sList = (TLinkList*)list;

LinkListNode* ret = NULL;

int i = 0;

if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )

{

LinkListNode* current = (LinkListNode*)sList;

for(i=0; i<pos; i++)

{

current = current->next;

}

ret = current->next;

}

return ret;

}

LinkListNode* LinkList_Delete(LinkList* list, int pos) // O(n)

{

TLinkList* sList = (TLinkList*)list;

LinkListNode* ret = NULL;

int i = 0;

if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )

{

LinkListNode* current = (LinkListNode*)sList;

for(i=0; i<pos; i++)

{

current = current->next;

}

ret = current->next;

current->next = ret->next;

sList->length--;

}

return ret;

}

main.c

#include <stdio.h>

#include <stdlib.h>

#include "LinkList.h"

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

struct Value

{

LinkListNode header;

int v;

};

int main(int argc, char *argv[])

{

int i = 0;

LinkList* list = LinkList_Create();

struct Value v1;

struct Value v2;

struct Value v3;

struct Value v4;

struct Value v5;

v1.v = 1;

v2.v = 2;

v3.v = 3;

v4.v = 4;

v5.v = 5;

LinkList_Insert(list, (LinkListNode*)&v1, LinkList_Length(list));

LinkList_Insert(list, (LinkListNode*)&v2, LinkList_Length(list));

LinkList_Insert(list, (LinkListNode*)&v3, LinkList_Length(list));

LinkList_Insert(list, (LinkListNode*)&v4, LinkList_Length(list));

LinkList_Insert(list, (LinkListNode*)&v5, LinkList_Length(list));

for(i=0; i<LinkList_Length(list); i++)

{

struct Value* pv = (struct Value*)LinkList_Get(list, i);

printf("%d\n", pv->v);

}

while( LinkList_Length(list) > 0 )

{

struct Value* pv = (struct Value*)LinkList_Delete(list, 0);

printf("%d\n", pv->v);

}

LinkList_Destroy(list);

return 0;

}

优点:

(1)无需一次性定制链表的容量。

(2)插入和删除操作无需移动数据元素。

缺点:

(3)数据元素必须保存后继元素的位置信息。

(4)获取指定数据的元素操作需要顺序访问之前的元素。

课后习题

1. 顺序表的实现中为什么保存的是具体数据元素的地址?而保存的地址存放在unsigned int中,而不是具体的指针类型中?为什么不是void*呢?

2. 以下关于链式存储结构的叙述中正确的是

A. 链式存储结构不是顺序存取结构。

B. 逻辑上相邻的结点物理上必相邻。

C. 可以通过计算直接确定第iii个元素 i个元素。

D. 插入和删除操作方便,不必移动其它结点。

3. 在单链表的实现和应用中,还有一种无表头结点的单链表。根据我们列出的操作,编程

实现这种无表头结点的单链表,并对比表头实现方式和无表头实现方式哪种更好。

4. 为我们实现的顺序表和单链表添加一个反转操作。这个操作使得链表中的次序反转,即第一 ,即第个元素变为最后一个元素,第二个元素变为倒

数第二个元素。如:abcd反转的结果为 反转的结果为

dcba。

要求时间复杂度达到O(n)。

SeqList_Reverse(SeqList* list);

LinkList_Reverse(LinkList* list);

转载于:https://www.cnblogs.com/free-1122/p/11322731.html

数据-第8课-线性表的链式存储结构(未)相关推荐

  1. 数据结构和算法:(3)3.2线性表的链式存储结构

    线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素也就是说你这个可以放在A地点,这个可以放在E地点,A地点和E地点中间可以隔开一个C地点和D地点,这样是允许的),这组存储单元可以存在 ...

  2. 链表list(链式存储结构实现)_5 线性表的链式存储结构

    系列文章参考资料为<大话数据结构>,源码为个人私有,未经允许不得转载 线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,可以使连续的,也可以不连续,也就意味这些元素可以 ...

  3. 从零开始学数据结构和算法(二)线性表的链式存储结构

    链表 链式存储结构 定义 线性表的链式存储结构的特点是用一组任意的存储单元的存储线性表的数据元素,这组存储单元是可以连续的,也可以是不连续的. 种类 结构图 单链表 应用:MessageQueue 插 ...

  4. 《数据结构》c语言版学习笔记——其他链表(线性表的链式存储结构Part2)

    线性表的链式存储结构 数据结构系列文章 第三章 循环链表.双向链表 文章目录 线性表的链式存储结构 前言 一.循环链表 (一)定义 (二)尾指针 二.双向链表 (一)定义 (二)代码 总结 前言 提示 ...

  5. 《数据结构》c语言版学习笔记——单链表结构(线性表的链式存储结构Part1)

    线性表的链式存储结构 数据结构系列文章 第二章 单链表结构 文章目录 线性表的链式存储结构 前言 一.单链表的建立 代码 二.单链表的读取 代码 三.单链表的插入 代码 四.单链表的删除 代码 五.单 ...

  6. 数据结构开发(5):线性表的链式存储结构

    0.目录 1.线性表的链式存储结构 2.单链表的具体实现 3.顺序表和单链表的对比分析 4.小结 1.线性表的链式存储结构 顺序存储结构线性表的最大问题是: 插入和删除需要移动大量的元素!如何解决? ...

  7. 线性表(链式存储结构)C语言

    文章目录 一.线性表的链式存储结构 二.代码 1.头文件与宏定义: 2.对链表的定义及主要使用函数: 3.测试函数(主函数): 三.运行结果 一.线性表的链式存储结构 线性表的链式存储结构的特点是用一 ...

  8. 【数据结构】CH2 线性表的链式存储结构

    目录 一.链表概述 1.相关定义 二.单链表 1.插入和删除节点的操作 (1)插入结点 (2)删除结点 2.建立单链表 (1)头插法 (2)尾插法 3.线性表基本运算在单链表中的实现 (1)初始化线性 ...

  9. 线性表的链式存储结构以及单链表的插入和删除原理实现

    线性表的链式存储结构 线性表中的每个元素最多只有一个前驱元素和一个后继元素(其逻辑结构),因此可以采用链式存储结构存储. 链表 线性表的链式存储结构称为链表.在链表中每个结点不仅包含有元素本身的信息( ...

  10. 数据结构-线性表(链式存储结构)

    线性表(链式存储结构) 特点: 用一组任意的存储单元存储线性表的数据结构,这组存储单元可以是连续的,也可以是不连续的. 对数据结构ai来说,除了存储其本身的信息之外,还需存储一个指示其后继的信息(即直 ...

最新文章

  1. KVM libvirt 虚拟机快照技术
  2. CacheDependency缓存依赖里面的 absoluteExpiration(绝对到期时间),弹性到期时间(slidingExpiration)...
  3. 卷积神经网络新手指南 2
  4. 壊小子的学习【程序开发学习篇】(一)培训时期的学习
  5. 树莓派apt-get下载网速太慢
  6. ubuntu常见错误--could not get lock /var/lib/dpkg/lock -open
  7. mysql varchar 1024_mysql中的数据类型
  8. boost::recursive_mutex相关的测试程序
  9. whether logo retrieval will block the application
  10. 计算机论文的的格式,计算机论文格式模板.doc
  11. Multi-thread--C++11中std::mutex的使用
  12. Python提示错误 module 'request' has no attribute 'urlretrieve'
  13. 厚积薄发 前端学习笔记 CSS基础篇-左侧固定,右侧自适应(或右侧固定,左侧自适应)布局方法...
  14. C# string 转 bool
  15. 成不了数据分析师,都是这些套路搞的鬼!
  16. 数学中的几种共轭类型
  17. Android SDK官网下载网址
  18. 驱动精灵安装的流氓软件如何卸载、及删除驱动精灵
  19. openwrt绑定ddns花生壳域名
  20. 【cvpr2022】ReSTR: Convolution-free Referring Image Segmentation Using Transformers

热门文章

  1. java中的堆和栈_实例理解Java中的堆和栈
  2. linux打印设备树,Linux 设备树(Device Tree)(转载)
  3. ora-12560:协议适配器错误
  4. android自定义View之曲线图
  5. 牛x!一个比传统数据库快 100-1000 倍的数据库!
  6. 面试鹅厂,我被虐的体无完肤。。。
  7. 基于 SurfaceView 的直播点亮心形效果
  8. linux 用用监听器,Linux/Unix shell 监控Oracle监听器(monitor listener)
  9. c++生成随机数_C 语言产生随机数的方法
  10. Selenium模拟浏览器常见操作及问题