DS02_线性表03_单链表

合集下载

DS02线性表习题参考解答

DS02线性表习题参考解答

第2章线性表习题参考解答一、简答题1.试描述头指针、头结点、开始结点的区别、并说明头指针和头结点的作用。

【答】头指针:是指向链表中的第一个结点的指针。

头结点:在开始结点之前附加上的一个结点。

开始结点:链表的第一个结点。

头指针是一个指向地址的变量,用于表示一个链表的开始。

引入头结点可以更加方便的进行链表是否为空的判断,同时方便了插入和删除结点。

开始结点用于存储链表的第一个数据元素。

2.何时选用顺序表、何时选用链表作为线性表的存储结构为宜?【答】顺序表中查找元素、获取表长非常容易,但是,要插入或者删除一个元素却需要移动大量的元素;相反,链表中却是方便插入或者删除元素,在查找元素的是,需要进行遍历。

因此,当所涉及的问题常常进行查找等操作,而插入、删除相对较少的是,适合采用顺序表;当常常需要插入、删除的时候,适合采用链表。

3.为什么在单循环链表中设置尾指针比设置头指针更好?【答】在单循环链表中,设置尾指针,可以更方便的判断链表是否为空。

4.在单链表、双链表和单循环链表中,若仅知道指针p指向某结点,不知道头指针,能否将结点*p从相应的链表中删去?【答】本题分三种情况讨论:1、单链表:当知道指针p指向某结点时,能够根据该指针找到其直接后继,但是不知道头指针,因此不能找到该结点的直接前趋,因此,无法删除该结点。

2、双链表:根据指针p可以找到该结点的直接前趋和直接后继,因此,能够删除该结点。

3、单循环链表:和双链表类似,根据指针p也可以找到该结点的直接前趋和直接后继,因此,也可以删除该结点。

5.下述算法的功能是什么?LinkList Demo(LinkList *L) /* L是无头结点单链表*/{LNode *Q,*P;if(L&&L->next){Q=L;L=L->next;P=L;while (P->next) P=P->next;P->next=Q; Q->next=NULL;}return L;} /* Demo */【答】将原来的第一个结点变成末尾结点,原来的第二个结点变成链表的第一个结点。

单链表数据结构

单链表数据结构

插入
if (p != NULL && j == i-1) { // 找到第i个结点
s = (LinkList) malloc ( sizeof (LNode)); // 生成新结点
s->data = e;
// 数据域赋值
s->next = p->next; //新结点指针指向后一结点
p->next = s; return OK;
6、销毁
4.6 销毁操作
while(L) { p = L->next; free(L); L=p;
// p指向第一结点(头节点为“哑结点”) // 释放首结点 // L指向p
}
// 销毁完成后,L为空(NULL)
算法的时间复杂度为:O(ListLength(L))
判空 求表长
4.7 其它操作
if(L->next==NULL) return TRUE; // 空
5、清空
4.5 清空操作
while (L->next) { p = L->next; L->next = p->next; free(p);
// p指向当前结点 // 头结点指向当前结点的后结点 // 释放当前结点内存
}
// 清空完成后,仍保留头结点L
算法的时间复杂度为:O(ListLength(L))
点。
5.1.2 逆序建立单链表
①建立一个带头结点的空单链表;
②输入数据元素ai,建立新结点p, 并把p插入在头结点之后成为第一个 结点。
③重复执行②步,直到完成单链表的 建立。
a1
a2 a1
创建出来的链表 点顺序与插入操作
顺序相反。

数据结构线性表ppt课件

数据结构线性表ppt课件

01
02
03
04
插入操作
在链表的指定位置插入一个新 节点,需要修改相邻节点的指
针。
删除操作
删除链表的指定节点,需要修 改相邻节点的指针。
查找操作
从链表的头节点开始,顺序遍 历链表,直到找到目标元素或
遍历到链表末尾。
遍历操作
从链表的头节点开始,顺序访 问每个节点,直到遍历到链表
末尾。
04 线性表应用举例 与问题分析
多项式表示与计算问题
01
02
03
多项式表示方法
数组表示法和链表表示法 。
数组表示法
将多项式的系数按次序存 放在一个数组中,通过下 标表示对应的幂次。
链表表示法
每个节点包含系数和指数 两个数据域,以及一个指 向下一个节点的指针域。
一元多项式相加算法设计
• 算法思想:将两个多项式中的同类项系数相加,得到新的 多项式。
删除操作
删除指定位置i的元素,需要将i之后的元素都向前移动 一个位置。
03 链式存储结构及 其实现
链式存储结构原理及特点
链式存储结构原理
使用一组任意的存储单元存储线 性表的数据元素(这组存储单元 可以是连续的,也可以是不连续 的)。
链式存储结构特点
逻辑上相邻的元素在物理位置上 不一定相邻,元素之间的逻辑关 系是通过指针链接来表示的。
...,an组成的有序序列。
性质
集合中必存在唯一的一个“第一元素 ”。
集合中必存在唯一的一个“最后元素 ”。
除最后元素之外,均有唯一的后继。
除第一元素之外,均有唯一的前驱。
线性表与数组关系
数组是线性表的一种表现和实现形式。
线性表更侧重于逻辑概念,而数组则是这种逻辑概念在计算机中的一种存储方式。

DS02_线性表1

DS02_线性表1

即:LOC(ai) = LOC(ai-1) + C
一个数据元素所占存储量↑
所有数据元素的存储位置均取决于
第一个数据元素的存储位置
LOC(ai) = LOC(a1) + (i-1)×C
↑基地址
SIE. BIT
数据结构与算法设计
线性表的顺序存储结构示意图
逻辑地址
0
数据元素
k0
存储地址 数据元素
Loc(k0) k0
SIE. BIT
数据结构与算法设计
链表的常用操作

获取表头指针;
求链表的长度;



寻找第i个数据元素;
根据关键字值求数据元素在链表中的位 置; 插入数据元素; 修改数据元素的值; 删除数据元素。
SIE. BIT

数据结构与算法设计
2.2 抽象链表类的定义
线性链表有3种:单链表、循环链表与双向链表; 抽象出上述三种线性链表的相同点(结点、指针和 相同操作),建立一个抽象链表类,再由此抽象链 表类派生出新的链表类(单链表和循环链表); 采用类模板机制; 增加表头结点,统一空表和非空表的操作,方便算 法设计。
010501
010502
令狐冲
王重阳
17
18


010503
010504 010505
曲洋
何铁手 李莫愁
17
19 16

女 女
SIE. BIT
数据结构与算法设计
1.2 线性表的顺序存储方式
在计算机内部可以采用两种不同方法来表示
一个线性表,它们分别是顺序表表示法和链
表表示法。
顺序表示法的定义; 元素的地址表示; 顺序表示法的优、缺点。

DS02_线性表_常见问题

DS02_线性表_常见问题

a=a-b;
作业

2.22 试写一算法,对单链表实现就地逆置。
p:指向已逆序链的第一个结点 q:指向待插入链的第一个结点 s:指向待插入链的第二个结点


问题:ADT


什么是抽象数据类型ADT? 抽象数据类型(Abstract Data Type,ADT):一个数学 模型以及定义在该模型上的一组操作的总称。 例P19 ADT线性表的定义 抽象数据类型是与表示无关的数据类型 抽象数据类型的设计者根据这些描述给出操作的具体实 现,抽象数据类型的使用者依据这些描述使用抽象数据 类型。 关键:使用它的人可以只关心它的逻辑特征,不需要了 解它的存储方式。
问题:ElemType

《实验一》中typedef int ElemType; ElemType是什么? 结点(也就是数据元素)类型

线性表:是n(n≥0)个具有相同类型的数据元素的有限序列。每个数据 元素表(A,B,C,……,Z) 数字,如 记录等

如果没有ElemType, P22顺序表的存储结构该如何定义?基本操作该如 何实现? 所有出现ElemType的地方都换成int?char?other else? 有了ElemType之后,对于某个特定应用我们只需typedef int ElemType; 或typedef char ElemType; 那么,现在我们可以理解为什么《实验一》中typedef int ElemType;
例p19adt线性表的定义抽象数据类型的设计者根据这些描述给出操作的具体实现抽象数据类型的使用者依据这些描述使用抽象数据类型
问题:for 语句的执行顺序



for语句的执行顺序 for语句格式为: for(表达式1;表达式2;表达式3) 语句:/*循环体*/ 该语句执行过程如下: 表达式1 (表达式2、循环体、表达式3)、 (表达式2、循环体、表达式 3)、 (表达式2、循环体、表达式3)、 (表达式2、循环体、表 达式3)…… 如 for (int a=0,i=0; i<10; ++i) { a+=i;}

数据结构教学课件:线性表链表

数据结构教学课件:线性表链表

头结点好处
a、由于开始结点的位置被存放在头结点的指针域中, 所以在链表的第一个位置上的操作(如插入、删 除等)就和在表的其它位置上的操作一致,无需 进行特殊处理; b、无论链表是否为空,其头指针是指向头结点的非 空指针(空表中头结点的指针域为空),头指针 始终不为空,因此空表和非空表的处理也就统一 了
}
带头结点的单链表 H
# a1 a2

an NULL
头结点
H
# NULL
头结点
linklist * initList() linklist * initList() { { linknode* pHead = (linknode*) linknode* pHead = 0; // pHead、 malloc( sizeof(linknode)); pRail分别为头、尾指针 linknode* pRail = pHead; linknode* pRail = pHead; // pHead、 char c; pRail分别为头、尾指针 char c; while( (c = getchar()) != ‘\n’) { linknode* pNode = while( (c = getchar()) != ‘\n’) { (linknode*)malloc( sizeof(linknod linknode* pNode = e )); (linknode*)malloc( sizeof( linknode scanf( "%c", &pNode->data ); )); scanf( "%c", &pNode->data ); pNode->next = 0; //新结点指 针域为空 pNode->next = 0; //新结点指针 pRail->next = pNode; 域为空 pRail = node; if( !pHead) pHead = pNode; } else pRail->next = pNode; return pHead; pRail = node; } } return pHead; }

DS第二章_课后习题答案教案资料

DS第二章_课后习题答案教案资料

D S第二章_课后习题答案第二章线性表2.1 填空题(1)一半插入或删除的位置(2)静态动态(3)一定不一定(4)头指针头结点的next 前一个元素的next2.2 选择题(1)A (2) DA GKHDA EL IAF IFA(IDA)(3)D (4)D (5) D2.3头指针:在带头结点的链表中,头指针存储头结点的地址;在不带头结点的链表中,头指针存放第一个元素结点的地址;头结点:为了操作方便,在第一个元素结点前申请一个结点,其指针域存放第一个元素结点的地址,数据域可以什么都不放;首元素结点:第一个元素的结点。

2.4已知顺序表L递增有序,写一算法,将X插入到线性表的适当位置上,以保持线性表的有序性。

void InserList(SeqList *L,ElemType x){int i=L->last;if(L->last>=MAXSIZE-1) return FALSE; //顺序表已满while(i>=0 && L->elem[i]>x){L->elem[i+1]=L->elem[i];i--;}L->elem[i+1]=x;L->last++;}2.5 删除顺序表中从i开始的k个元素int DelList(SeqList *L,int i,int k){int j,l;if(i<=0||i>L->last) {printf("The Initial Position is Error!"); return 0;}if(k<=0) return 1; /*No Need to Delete*/if(i+k-2>=L->last) L->last=L->last-k; /*modify the length*/for(j=i-1,l=i+k-1;l<L->last;j++,l++)L->elem[j]=L->elem[l];L->last=L->last-k;return 1;}2.6 已知长度为n的线性表A采用顺序存储结构,请写一时间复杂度为O(n)、空间复杂度为O(1)的算法,删除线性表中所有值为item的数据元素。

单链表的基本概念

单链表的基本概念

插入节点
01
找到插入位置
遍历链表,找到需要插入新节点 的位置。
02
03
创建新节点
调整指针
创建一个新的节点,并设置其数 据域。
将新节点的指针指向原位置的下 一个节点,同时将前一个节点的 指针指向新节点。
删除节点
找到待删除节点
遍历链表,找到需要删除的节点。
调整指针
将待删除节点的前一个节点的指针指向待删除节 点的下一个节点,从而跳过待删除节点。
合并两个有序链表
遍历两个链表,比较当前节点的数据大 小,将较小的节点插入到新链表的末尾。
重复上述过程,直到其中一个链表遍历完成。
将剩余未处理的节点直接链接到新 链表的末尾。
合并两个有序链表
注意事项
1
2
在插入节点时需要注意更新前一个节点的指针。
3
可以使用哑节点来简化头节点的处理过程。
THANKS.
合并两个有序链表
• 问题描述:合并两个有序链表是计算机科学中的一个常见问题,可以使用单链表来表示两个有序序列,通过遍 历两个链表并将节点按照大小插入到新的链表中,得到最终的合并结果。
合并两个有序链表
实现步骤 定义单链表节点结构,包含数据和指向下一个节点的指针。
创建两个有序链表,分别表示要合并的两个序列。
存储空间额外开销
由于每个节点都需要存储指针信息,因此链表相对于数组有一定的 空间开销。
链表的应用场景
动态数据结构
链表适用于需要动态调整大小的数据结构,如实现动态数 组、栈、队列等。
元素插入和删除频繁的场景
链表在元素插入和删除操作上具有优势,适用于需要频繁 进行这些操作的场景,如编辑器的文本处理、网络数据包 的传输等。

数据结构链表操作知识点汇总

数据结构链表操作知识点汇总

数据结构链表操作知识点汇总在计算机科学中,数据结构是组织和存储数据的方式,以便能够高效地访问和操作数据。

链表是一种常见的数据结构,它在很多程序中都有着广泛的应用。

下面就让我们来详细了解一下链表操作的相关知识点。

链表是一种线性的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针(在双向链表中,还包含指向前一个节点的指针)。

与数组不同,链表中的元素在内存中不是连续存储的,这使得链表在插入和删除操作上具有很大的优势。

一、链表的基本类型1、单向链表单向链表中,每个节点只包含指向下一个节点的指针。

这意味着我们只能从链表的头部开始,依次遍历到尾部。

2、双向链表双向链表中的节点除了指向下一个节点的指针,还有指向前一个节点的指针。

这使得我们可以从链表的两端进行遍历,并且在某些操作(如删除节点)时更加方便。

3、循环链表循环链表的尾节点指向头节点,形成一个环形结构。

这在一些特定的场景中,如实现某些算法时非常有用。

二、链表的操作1、创建链表创建链表通常需要定义一个节点结构体,然后通过动态分配内存来创建节点,并将节点连接起来形成链表。

2、插入节点插入节点可以分为在链表头部插入、在链表尾部插入和在链表中间插入。

在头部插入时,新节点成为链表的新头部,其指针指向原来的头部节点。

在尾部插入,需要先找到尾部节点,然后将新节点连接到尾部。

在中间插入,需要先找到插入位置的前一个节点,然后调整指针完成插入。

3、删除节点删除节点需要先找到要删除的节点,然后调整其前后节点的指针,释放被删除节点的内存。

4、查找节点查找节点通常需要从链表的头部开始,依次比较节点中的数据,直到找到目标节点或遍历完整个链表。

5、遍历链表遍历链表是指依次访问链表中的每个节点,获取节点中的数据。

三、链表操作的时间复杂度1、插入操作在头部或尾部插入节点的时间复杂度为 O(1),因为只需要修改几个指针。

在中间插入节点的时间复杂度为 O(n),因为需要先找到插入位置。

DS02-线性表

DS02-线性表

插入前 插入后
图2.2 在顺序表中插入结点的示意图
算法2.4 在表L的第i个位置插入数据item
int Ins(sequenlist *L,int i,datatype item)
{int j;
if(i<0 || i>L->length) return FALSE;
for(j=L->length-1;j>=i;j--)/*注意数组的下标从0开始*/
L-> length=0; }
顺序表的基本操作
清除一个线性表的内容 要清除一个已经存在的线性表的内容,
只需要把该线性表设置为空表,也就是把 表长置为0。 算法2.2 清除一个线性表的内容 void ClearList(sequenlist *L)
{ L->length=0; } 本算法时间复杂度为O(1)。
LOC(ai+1)=LOC(ai)+m 线性表L的第i个元素的存储位置和第一 个元素的存储位置的关系为:
LOC(ai)=LOC(a1)+(i-1)*m 其中LOC(a1)是线性表的第一个数据元素的存 储位置,通常称为线性表的起始位置或基地址。
顺序表的基本操作
顺序表的C语言描述
typedef int datatype; /*定义表元素类型*/
算法2.3 定位(按值查找)
int Loc(sequenlist L,datatype Item)
{ int i,j;
j=L.length; /*表的长度*/
if( j= = 0) return -1; for(i=0;i<=j-1;i++)
找到了值为item的结点
{ if(L. data[i]= =Item) return i; }

DS02-线性表

DS02-线性表
newnode→link = p→link; if ( p→link ==NULL ) last = newnode; p→link = newnode;
/*结点数为0返回空表*/
head=(NODE*)malloc(sizeof(NODE)); /*申请建立第一个结点*/
p=head;
for (i=1;i<n;i++)
{scanf(“%c”,&(p->data));
/*输入结点元素的值*/
q= (NODE*)malloc(sizeof(NODE)); /*申请建立下一个结点*/
如:#define MAXSIZE 100 struct {char 学号;
char 姓名; int 数据结构; int 操作系统; int 离散数学; int 英语}list[MAXSIZE]; int n;
2 线性表的创建程序: 设list[]为已定义的存放线性表的数组,n为线
性表的长度。
Void creat_sq_list(int n,list[]) { int i;
链表结点通过(NODE*)malloc(sizeof(NODE))函数获得。
线性链表的创建程序 建立n个结点的单链表函数,返回链表的头指针。
NODE *creat_link_list(int n)
{int i;
NODE *head,*p,*q; /*p指向正链表最后结点,q指向新申请结点*/
if (n==0)return(NULL);
int sq_del(list,n,i)
int list[], *n, i;
{int j;
if(i<0||i>*n) return(1); /*第1种情况,i不在可删除位置上*/

线性表知识点总结

线性表知识点总结

线性表知识点总结线性表是数据结构中一种非常基础且重要的数据结构,它在计算机科学和程序设计中有着广泛的应用。

接下来,让我们详细了解一下线性表的相关知识点。

一、线性表的定义线性表是由零个或多个数据元素组成的有限序列。

这里的“有限”意味着线性表中的元素个数是确定的。

每个元素在表中的位置是按照顺序排列的,并且具有前驱和后继的关系,除了第一个元素没有前驱,最后一个元素没有后继。

二、线性表的特点1、元素之间存在顺序性:线性表中的元素按照一定的顺序排列,每个元素都有其特定的位置。

2、元素个数有限:线性表中的元素数量是有限的,不能是无限的。

3、元素类型相同:线性表中的元素具有相同的数据类型,这样便于进行统一的操作和处理。

三、线性表的存储结构1、顺序存储定义:顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素。

优点:可以随机访问表中的任意元素,查找操作效率高;存储密度高,不需要额外的指针来表示元素之间的关系。

缺点:插入和删除操作可能需要移动大量元素,效率较低;预先分配的存储空间可能会造成浪费或不足。

2、链式存储定义:链式存储是通过指针将各个元素链接起来,每个元素由数据域和指针域组成。

优点:插入和删除操作不需要移动大量元素,效率较高;不需要预先分配固定的存储空间,更加灵活。

缺点:不能随机访问,查找操作需要从头指针开始遍历,效率较低;存储密度较低,需要额外的指针空间。

四、线性表的基本操作1、初始化:创建一个空的线性表。

2、销毁:释放线性表所占用的存储空间。

3、清空:将线性表中的元素全部删除,使其成为一个空表。

4、判断是否为空:判断线性表是否为空。

5、求长度:返回线性表中元素的个数。

6、取值:获取指定位置的元素值。

7、查找:在线性表中查找指定元素。

8、插入:在指定位置插入一个新元素。

9、删除:删除指定位置的元素。

五、顺序表的实现1、定义数据类型通常使用一个数组来存储顺序表的元素,并使用一个整数来记录表的长度。

数据结构及单链表

数据结构及单链表

数据结构及单链表在我们的数字世界里,数据结构就像是一个个神奇的魔法盒子,而单链表就是其中特别有趣的一个。

我记得有一次,我去朋友家,他正在为一个编程作业发愁,题目就是关于单链表的操作。

他苦着脸跟我说:“这单链表咋就这么难搞呢,一会儿插入节点,一会儿删除节点,搞得我头都大了!”我笑着跟他说:“别着急,咱们一起来看看。

”咱先来说说啥是数据结构。

简单来讲,数据结构就是数据的组织方式,就像你整理房间,把衣服放衣柜,鞋子放鞋柜,书放书架,这就是一种“结构”。

在计算机里,数据也得有合理的组织方式,这样才能方便我们快速地查找、插入和删除数据。

那单链表呢,就像是一列排好队的小朋友,每个小朋友只知道后面的是谁,不知道前面的是谁。

比如说,第一个小朋友后面是第二个,第二个后面是第三个,依次类推。

这就是单链表的特点啦,每个节点(就像小朋友)只包含数据和指向下一个节点的指针。

想象一下,我们要在这个队伍中间插入一个新的小朋友。

那我们只需要让前面的小朋友指向新的小朋友,新的小朋友再指向下一个原来的小朋友,这是不是很简单?删除也是类似的道理,把前后的指针调整一下就行。

在实际编程中,单链表的应用可多了。

比如说,我们要记录用户的浏览历史,就可以用单链表。

每次用户访问一个新页面,就把这个页面的信息加到链表的末尾。

当我们需要查看历史或者删除一些历史记录时,单链表的操作就能派上用场。

再比如,在一个音乐播放列表中,我们可以用单链表来存储歌曲。

播放下一首的时候,就顺着链表往下走。

如果要删除不喜欢的歌曲,也能轻松搞定。

我还记得我刚开始学习单链表的时候,总是会搞错指针的指向,导致程序出错。

但经过不断地练习和调试,我终于掌握了其中的窍门。

就像骑自行车,一开始摇摇晃晃,但掌握了平衡之后,就能自由驰骋。

总之,数据结构中的单链表虽然看起来有点复杂,但只要我们多练习、多思考,就一定能掌握它的奥秘,让它为我们的编程之路助力。

就像朋友那次作业,在我的帮助下,他终于搞懂了,脸上露出了开心的笑容。

DS-课后习题答案

DS-课后习题答案

第二章线性表2.1填空题(1)一半插入或删除的位置(2)静态动态(3)一定不一定(4)头指针头结点的next前一个元素的next2.2选择题(1)A (2) DA GKHDA EL IAF IFA(IDA)(3)D (4)D (5) D2.3头指针:在带头结点的链表中,头指针存储头结点的地址;在不带头结点的链表中,头指针存放第一个元素结点的地址;头结点:为了操作方便,在第一个元素结点前申请一个结点,其指针域存放第一个元素结点的地址,数据域可以什么都不放;首元素结点:第一个元素的结点。

2.4已知顺序表L递增有序,写一算法,将X插入到线性表的适当位置上,以保持线性表的有序性。

void InseiList(SeqList *L,ElemType x)(hit i=L->last;if(L->last>=MAXSIZE-1) renun FALSE; 〃顺序表已满while(i>=0 && L->elem[i]>x)(L->elem[i+1 ]=L->elem[i];i-;}L->elem[i+l]=x;L->last++;}2.5删除顺序表中从i开始的k个元素hit DelList(SeqList *L,int k)(if(i<=O||i>L->last) {prmtf(n The Initial Position is Error!H); return 0;}if(k<=0) return 1; /*No Need to Delete*/if(i+k-2>=L->last) L->last=L->last-k;芦modify the length*/精选fdr(j=i-l J=i+k-l ;l<L->last;j-H-J++)L->elem[j]=L->elem[l];L->last=L->last-k;return 1;}2.6已知长度为n的线性表A采用顺序存储结构,请写一时间发杂度为O(n)、空间更杂度为0(1)的算法,删除线性表中所有值为item的数据元素。

线性表的概念

线性表的概念

线性表的概念线性表是数据结构中最基本的一种,它是由n个具有相同数据类型的数据元素组成的有限序列。

线性表的特点是数据元素之间的关系是一对一的,即每个数据元素都只有一个直接前驱和一个直接后继。

线性表可以用顺序存储结构或链式存储结构来实现。

顺序存储结构是将线性表中的数据元素按其逻辑顺序依次存储在一组地址连续的存储单元中,这样就可以通过元素在存储器中的相对位置来表示元素之间的逻辑关系。

而链式存储结构则是通过指针来实现数据元素之间的逻辑关系,每个数据元素都有一个指针域,指向其直接后继元素的存储位置。

线性表的应用十分广泛,它在计算机科学领域中有着重要的地位。

下面我们将从几个方面来探讨线性表的应用。

首先,线性表可以用来实现栈和队列。

栈是一种先进后出的数据结构,而队列是一种先进先出的数据结构。

它们都可以通过线性表来实现,栈可以用顺序存储结构或链式存储结构来实现,而队列通常使用链式存储结构来实现。

其次,线性表可以用来实现线性表。

在实际的软件开发中,经常需要对数据进行排序操作,而线性表提供了一个非常方便的数据结构来实现排序算法。

常见的排序算法有冒泡排序、选择排序、插入排序、快速排序等,它们都可以通过线性表来实现。

另外,线性表还可以用来实现线性表。

线性表可以用来表示多项式,多项式的加法、减法、乘法等运算都可以通过线性表来实现。

这在数学计算和科学计算中有着重要的应用。

此外,线性表还可以用来实现图的邻接表。

图是一种非线性的数据结构,它由顶点的有限集合和顶点之间边的集合组成。

图的邻接表是一种常用的表示方法,它可以通过线性表来实现。

邻接表中的每个顶点都对应一个线性表,用来存储与该顶点相邻的顶点。

总的来说,线性表作为数据结构中最基本的一种,它在计算机科学领域中有着广泛的应用。

通过线性表,我们可以实现栈和队列、排序算法、多项式运算、图的邻接表等功能。

因此,对线性表的深入理解和掌握对于计算机科学领域的学习和工作都是非常重要的。

希望通过本文的介绍,读者能对线性表有一个更深入的理解,并能够在实际的应用中灵活运用线性表。

数据结构与算法(二)-线性表之单链表顺序存储和链式存储

数据结构与算法(二)-线性表之单链表顺序存储和链式存储

数据结构与算法(⼆)-线性表之单链表顺序存储和链式存储前⾔:前⾯已经介绍过数据结构和算法的基本概念,下⾯就开始总结⼀下数据结构中逻辑结构下的分⽀——线性结构线性表⼀、简介1、线性表定义 线性表(List):由零个或多个数据元素组成的有限序列; 这⾥有需要注意的⼏个关键地⽅: 1.⾸先他是⼀个序列,也就是说元素之间是有个先来后到的。

2.若元素存在多个,则第⼀个元素⽆前驱,⽽最后⼀个元素⽆后继,其他元素都有且只有⼀个前驱和后继。

3.线性表强调是有限的,事实上⽆论计算机发展到多钱⼤,他所处理的元素都是有限的。

使⽤数学语⾔来表达的话: a1,…,ai-1,ai,ai+1,…an 表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。

所以线性表元素的各数n(n>0)定义为线性表的长度,当n=0时,称为空表。

2、抽象数据类型 数据类型:是指⼀组性质相同的值得集合及定义在此集合上的⼀些操作的总称。

例如很多编程语⾔的整型,浮点型,字符型这些指的就是数据类型。

不同的数据结构满⾜不同的计算需求,所以出现了各种各样样的数据类型,它可以分为两类: 1.原⼦类型:不可以再分解的基本数据类型,例如整型、浮点型等; 2.结构类型:有若⼲个类型组合⽽成,是可以再分解的,例如整型数组是由若⼲整型数据组成的; 抽象:是指抽取处事务具有的普遍性的本质。

他要求抽出问题的特征⽽忽略⾮本质的细节,是对具体事务的⼀个概括。

抽象是⼀种思考问题的⽅式,他隐藏了复杂的细节。

⽽我们对数据类型进⾏抽象,就有了抽象数据类型,抽象数据类型是指⼀个数据模型及定义在该模型上的⼀组操作。

抽象数据类型的定义仅取决于它的⼀组逻辑特性,⽽与其在计算机内部如何表⽰和实现⽆关。

抽象数据类型表⽰:ADT 抽象数据类型 Data 数据结构 Operation 具体数据操作(例,增删改查) ⽐如1+1=2这样⼀个操作,在不同CPU的处理上可能不⼀样,但由于其定义的数学特性相同,所以在计算机编程者看来,它们都是相同的。

线性表(单链表、循环链表-python实现)

线性表(单链表、循环链表-python实现)

线性表(单链表、循环链表-python实现)⼀、线性表 线性表的定义: 线性表是具有相同数据类型的有限数据的序列。

线性表的特点: 出了第⼀个元素外,每个元素有且仅有⼀个直接前驱,除最后⼀个元素外有且只有⼀个后继。

线性表是⼀种逻辑结构,表⽰元素之间的⼀⼀的相邻关系,顺序表和链表是指存储结构,两者属于不同的概念。

线性表的顺序表⽰: 线性表的顺序存储即数组的动态、静态分配,特点是可以随机访问。

线性表的链式表⽰: 线性表的链式存储即单链表、双连表、循环单链表以及循环双连表,特点是随机插⼊,不可随机访问。

单链表的实现(python):#定义每个节点class Node:def__init__(self,data):self.data=dataself.next=Noneclass linkList:#初始化头结点def__init__(self,n):self.head=Node(None)self.n=n#头插法建⽴链表def listCreateForward(self):if self.n==0:return Falseelse:temp=self.headfor i in range(1,self.n+1):print('请输⼊第{0}个节点:'.format(i))num = input()node = Node(num)node.next=temp.nexttemp.next = node#尾插法建⽴链表def listCreateBackward(self):if self.n==0:return Falseelse:temp=self.headfor i in range(1,self.n+1):print('请输⼊第{0}个节点:'.format(i))num = input()node = Node(num)temp.next=nodetemp=node#读取链表def readList(self):if self.n==0:print("空链表!")else:temp = self.headwhile temp.next!=None:temp = temp.nextprint(temp.data,end='')#链表长度def Length(self):i=0temp=self.headwhile temp.next!=None:temp=temp.nexti+=1return i#按值查找def locateElem(self,num):i = 0temp = self.headwhile temp.next != None:temp = temp.nexti += 1if int(temp.data)==num:return ireturn None#按位置查找def getElem(self,j):i = 0temp = self.headwhile temp.next != None:temp = temp.nexti += 1if int(j)==i:return temp.datareturn None#按位置插⼊数字def listInsert(self,j,num):if int(j)<0:return Noneelif self.Length()<j:return Noneelse:i = 0temp = self.headwhile temp.next != None:i += 1if int(j) == i:node=Node(num)node.next=temp.nexttemp.next=nodetemp = temp.next#删除特定元素def deleteData(self,num):temp=self.headwhile True:if temp.next==None:break#当这个节点是尾节点时if int(temp.next.data)==num and temp.next.next==None: temp.next=Nonebreakelif int(temp.next.data)==num:temp.next=temp.next.nexttemp=temp.next#删除特定位置的元素def deleteElem(self,j):if j==1:self.head.next=self.head.next.nextelif j==self.Length() :temp=self.head.nextwhile True:if temp.next.next==None:temp.next=Nonebreaktemp=temp.nextelif j<self.Length():i=2temp=self.head.nextwhile True:if i==j:temp.next=temp.next.nextelse:print('erro')return Nonelinklist1=linkList(5)linklist1.listCreateBackward()linklist1.readList()length=linklist1.Length()print('length={0}'.format(length))locate=linklist1.locateElem(5)print('5在位置{0}'.format(locate))data=linklist1.getElem(3)print('第3个位置是{0}'.format(data))linklist1.listInsert(1,111)linklist1.readList()print('\n删除111(第⼀个元素):')linklist1.deleteData(111)linklist1.readList()print('\n删除5(末尾的元素)')linklist1.deleteData(5)linklist1.readList()print('\n删除第⼀个元素:')linklist1.deleteElem(1)linklist1.readList()print('\n删除末尾的元素')linklist1.deleteElem(3)linklist1.readList()结果:请输⼊第1个节点:1请输⼊第2个节点:2请输⼊第3个节点:3请输⼊第4个节点:4请输⼊第5个节点:51 2 3 4 5 length=55在位置5第3个位置是3111 1 2 3 4 5删除111(第⼀个元素):1 2 3 4 5删除5(末尾的元素)1 2 3 4删除第⼀个元素:2 3 4删除末尾的元素2 3 循环链表的实现(python):其它部分与单链表相似#定义节点class Node:def__init__(self,data):self.data=dataself.next=Noneclass circleList:# 初始化头结点def__init__(self,n):self.head=Node(None)self.head.next=self.headself.n = n# 头插法建⽴链表-def listCreateForward(self):if self.n==0:return Falseelse:temp=self.headfor i in range(1,self.n+1):print('请输⼊第{0}个节点:'.format(i))num = input()node = Node(num)node.next=temp.nexttemp.next = node temp=temp.next# 尾插法建⽴链表def listCreateBackward(self):if self.n==0:return Falseelse:temp=self.headfor i in range(1,self.n+1):print('请输⼊第{0}个节点:'.format(i))num = input()node = Node(num)temp.next=nodetemp=nodetemp.next = self.head#读取循环链表def readList(self):if self.n==0:print("空链表!")else:temp = self.headwhile temp.next!=self.head: temp = temp.nextprint(temp.data,end='') linklist1=circleList(5)linklist1.listCreateForward()linklist1.readList()linklist1=circleList(5)linklist1.listCreateBackward() linklist1.readList()。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单链表的删除
Status ListDelete(LinkList L,int i,ElemType &e) // 算法2.10。不改变L { // 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 if (i<1) return ERROR; // i合法性检查 int j = 0; LinkList p = L, q; while (p->next && j<i-1) // p指向第i-1个结点 { p=p->next; ++j; } if (!p->next) // i>表长,此时p指向终端结点,返回出错信息 return ERROR; q = p->next; // 删除并释放结点 p->next = q->next; e = q->data; 设链表的长度为n 设链表的长度为n,合法的删除 free(q); q = NULL; 位置是1≦i≦n 1≦i≦n。 位置是1≦i≦n。 return OK; }
头结点
我们一般会在第一个结点之前附设一个类型相同的结点, 称之为头结点。 其数据域可以不存储任何信息,也可存储如线性表长度等 附加信息 注意:与首(元)结点的概念不同 空表 带头结点的空表 head=NULL 非空表 head a 1 a2 head ∧
an

带头结点的非空表 head a
1
a2
an
单链表的删除
算法分析 1. 工作指针 初始化;计数器 清零; 工作指针p初始化 计数器j清零 初始化; 清零; 2. 查找第 个结点并使工作指针 指向该结点; 查找第i-1个结点并使工作指针 指向该结点; 个结点并使工作指针p指向该结点 3. 若p不存在或 不存在后继结点,则抛出位置异常; 不存在或p不存在后继结点 不存在或 不存在后继结点,则抛出位置异常; 否则, 否则, 3.1 暂存被删结点和被删元素值; 暂存被删结点和被删元素值; 3.2 摘链,将结点 的后继结点从链表上摘下; 摘链,将结点p的后继结点从链表上摘下 的后继结点从链表上摘下; 3.3 返回被删元素值; 返回被删元素值; 3.4 释放被删结点; 释放被删结点;
单链表的基本操作
GetElem_L, ListInsert_L, ListDelete_L, CreateList_L MergeList_L
单链表的按位查找
单链表不能象顺序表中那样直接按序号i访问结点,而只能 从链表的头指针出发,顺链域next逐个结点往下搜索,直 到搜索到第i个结点为止。 设单链表的长度为n,要查找表中第i个结点,仅当1≦i≦n 时,i的值是合法的。我们将头结点看做是第0个结点,其 算法如下:
查找第i个结点。 如果不存在, 返回NULL。
单链表的删除
操作接口: 操作接口: Status ListDelete(LinkList L,int i,ElemType &e) 单链表中删除结点a 时指针的变化状况? 单链表中删除结点 i时指针的变化状况?
p q
L
a1 算法描述: 算法描述:
ai-1
ai
ai+1
q=p->next; e=q->data; p->next=q->next; free(q);
单链表的删除
注意分析边界情Biblioteka ——表头、表尾。 表头、 注意分析边界情况 边界情况 表头 表尾。
p q p q
L
a1
a2
an ∧
算法描述: 算法描述:
q=p->next; e=q->data; p->next=q->next; free(q);
单链表的插入---伪码
1. 位置指针p初始化;计数器j清零; 2. 查找第i-1个结点并使位置指针p指向该结点; 3. 若查找不成功,说明插入位置不合理,抛出插入位置异常; 否则, 3.1 生成一个元素值为e的新结点s; 3.2 将新结点s插入到结点p之后。 另一种伪码 Locate i-1’th element Allocate memory for the new node Point the new node to its successor Point the new node’s predecessor to the new node
0325 0300 0208 0200
… a2 0325 a1 0200 … a4 ∧ … a3 0300 … a3 a4 ʌ
a1
a2
单链表的画法
a1 的指针。 LinkList由若干结点构成 每个结点包括 data:数据域, 存储数据元素 next:指针域, 存储指向后继结点的指针, 也称链域 数据域 data 指针域 next a2 a3 a4 ʌ 通常,将链表画成一个有序的结点串,用箭头表示链域中
单链表的建立
单链表的插入
Status ListInsert(LinkList L,int i,ElemType e) // 算法2.9。 { // 在带头结点的单链线性表L中第i个位置之前插入元素e if (i<1) return ERROR; // i合法性检查 LNode p = L, s; int j=0; while (p && j<i-1) // 寻找第i-1个结点 { p = p->next; j++; } if (!p) // i > 表长+1 return ERROR; s = (LinkList)malloc(sizeof(LNode)); // 生成新结点 s->data = e; s->next = p->next; 设链表的长度为n 设链表的长度为n,合法的插入 p->next = s; 位置是1≦i≦n+1 1≦i≦n+1。 位置是1≦i≦n+1。 return OK; }
第2章 线性表
2.3 线性表的链式表示和实现
List Overview
Linked lists Abstract data type (ADT) Basic operations of linked lists GetElem, Insert, Delete, Create,Merge,Print, etc. Variations of linked lists Circular linked lists Doubly linked lists
L
a1
ai-1
③ ①s
ai

an ∧
算法描述: 算法描述: ① s=(LinkList)malloc(sizeof(LNode)); s->data=e; ② s->next=p->next; ③ p->next=s;
e
单链表的插入
注意分析边界情况——表头、表尾。 表头、 注意分析边界情况 边界情况 表头 表尾。 p p
单链表的删除
设单链表的长度为n,则删去第i个结点仅当1≦i≦n时是 合法的。 注意,当i=n+1时,虽然被删结点不存在,但其前趋结点 却存在,它是终端结点。因此被删结点的直接前趋*p存在 并不意味着被删结点就一定存在,仅当*p存在且*p不是终 端结点 (即p–>next!=NULL)时,才能确定被删结点存在。 显然此算法的时间复杂度也是O(n)。 从上面的讨论可以看出,链表上实现插入和删除运算,无 须移动结点,仅需修改指针。
单链表的画法
非空表 head a 1 空表 head=NULL a2 an ∧
单链表存储结构
显然,单链表可以由表头唯一确定,因此单链表可以用头 指针的名字来表示。 C语言描述的单链表存储结构如下(记忆) typedef struct LNode{ ElemType data; struct LNode *next; }LNode,*LinkList; 假设L是LinkList型的变量,则L为单链表的头指针,它指向 表中第一个结点。 单链表的结点结构: data next
2.3.1 线性链表
存储思想:用一组任意的存储单元存放线性表的元素 。任意指的是这组存储单元可以: 连续 不连续
单链表的存储
例:(a1, a2 ,a3, a4)的存储示意图 存储特点: 1.逻辑次序和物理次序不一定相同。 2.元素之间的逻辑关系用指针表示。 头指针:指向第一个结点 每一个结点增加一个指针域:指向 其后继结点 尾指针:终端结点的指针域为 NULL(即0)。

头结点的作用
(1) 统一插入和删除操作 对链表的插入和删除操作,都需修改前驱结点的指针域 对不带头结点的链表,首元结点没有前驱结点,在之前的 插入或删除操作比有前驱的其他结点要复杂。 对带头结点的链表,所有结点都有前驱结点,操作一致。 (2) 统一空表和非空表的处理 对带头结点的链表,表头指针是指向头结点的非空指针, 因此空表与非空表的处理是一样的。
单链表的按位查找
Status GetElem(LinkList L, int i, ElemType &e); p p p p p
L
a1
a2
ai
查找成功
an ∧
查找失败
核心操作(关键操作):位置指针后移。从头结点( 核心操作(关键操作):位置指针后移。从头结点(或开始 ):位置指针后移 结点)出发,通过位置指针的反复后移而将整个单链表“ 结点)出发,通过位置指针的反复后移而将整个单链表“审视 一遍的方法称为扫描 或遍历)。 扫描( ”一遍的方法称为扫描(或遍历)。
L e
a1
s
ai
an ∧ e ∧ s
由于单链表带头结 表头、表中、 点,表头、表中、 表尾三种情况的操 作语句一致。 作语句一致。
算法描述: 算法描述: ① s=(LinkList)malloc(sizeof(LNode)); s->data=e; ② s->next=p->next; ③ p->next=s;
相关文档
最新文档