线性表顺序存储结构代码

合集下载

数据结构 线性表

数据结构 线性表

第1讲线性表本章主要掌握如下内容:线性表的定义和基本操作,线性表的实现,线性表的顺序存储结构及链式存储结构,线性表的应用。

知识点分析(一)线性表的定义和基本操作1.线性表基本概念1)定义:是由相同类型的结点组成的有限序列。

如:由n个结点组成的线性表(a1, a2, …, a n)a1是最前结点,a n是最后结点。

结点也称为数据元素或者记录。

2)线性表的长度:线性表中结点的个数称为其长度。

长度为0的线性表称为空表。

3)结点之间的关系:设线性表记为(a1,a2,…a i-1 , a i, a i+1 ,…a n),称a i-1是a i的直接前驱结点....(简称前驱),a i+1是a i的直接后继结点....(简称后继)。

4)线性表的性质:①线性表结点间的相对位置是固定..的,结点间的关系由结点在表中的位置确定。

②如果两个线性表有相同的数据结点,但它们的结点顺序不一致,该两个线性表也是不相等的。

注意:线性表中结点的类型可以是任何数据(包括简单类型和复杂类型),即结点可以有多个成分,其中能唯一标识表元的成分称为关键字(key),或简称键。

以后的讨论都只考虑键,而忽略其它成分,这样有利于把握主要问题,便于理解。

『经典例题解析』线性表的特点是每个元素都有一个前驱和一个后继。

( )【答案】错误。

【解析】线性表的第一个数据元素没有前驱,最后一个元素没有后继。

其余的所有元素都有一个前驱和后继。

2.线性表的抽象数据类型线性表是一个相当灵活的数据结构,其长度可以根据需要增加或减少。

从操作上讲,用户不仅可以对线性表的数据元素进行访问操作,还可以进行插入、删除、定位等操作。

1)线性表的基本操作假设线性表L有数据对象 D={ai | ai∈ElemSet,i=1,2,3,…,n,n>=0},数据元素之间的关系R={<ai-1,ai>|ai-1,ai∈D,i=1,2,…,n},则线性表L的基本操作如下所示:●InitList(&L):其作用是构造一个长度为0的线性表(空线性表);●DestoryList(&L):其作用是销毁当前的线性表L;●ClearList(&L):清空线性表L,使之成为空表;●ListLength(L):返回线性表L的长度,即线性表中数据元素的个数;●ListEmpty(L) :判断线性表L是否为空表,是则返回True,否则返回False;●GetElem(L,i,&e):将线性表L中第i个数据元素的值返回到变量e中;●LocateELem(L,e,compare( )) :判断线性表L中是否存在与e满足compare()条件的数据元素,有则返回第一个数据元素;●PriorElem(L,cur_e,&pri_e):返回线性表L中数据元素cur_e的前驱结点;●NextElem(L,cur_e,&next_e):返回线性表L中数据元素cur_e的后继结点;●ListInsert(&L,i,e):向线性表L的第i个位置之前插入一个数据元素,其值为e;●ListDelete(&L,i,&e):删除线性表L的第i个数据元素,并将该数据元素的值返回到e中;●ListTraverse(L,visit()):遍历线性表中的每个数据元素。

《数据结构》课件第二章

《数据结构》课件第二章

线性表的基本操作(逻辑)
➢ 构造一个空表L ➢ 获取L的长度(即元素个数) ➢ 访问L中第i个数据元素的值 ➢ 访问L中第i个数据元素的前驱/后继的值 ➢ 在L中第i个元素之前插入新的元素e ➢ 删除L的第i个数据元素
➢ 注意在插入或者删除之后,线性表的长度应 能随之改变
一 顺序存储
➢ 线性表的顺序表示:用一组地址连续的存储单 元依次存储线性表的数据元素。

将Temp_b插入到 LC的第k个位置上
Temp_a ≤ Temp_b
是 将Temp_a插入到 LC的第k个位置上
否 i ≤ LA.len 否
j← j + 1
i← i + 1
j ≤ LB.len
Temp_a = Temp_b



j← j + 1
k← k + 1
结束

将LA表的第i个元 素插入到LC表的
插入操作的时间复杂度 O(n/2) 链表中的插入、删除操作没有上溢的情况, 并且节省内存资源
思考:若现已知道指向某元素节点的指针 p,希望能在该节点之前插入元素x,该如 何操作?其算法时间复杂度是多少?
3) 单链表的删除
p
删除第i个元素,由e返回值 删除b
a
Hale Waihona Puke bc … 1) 寻找第i-1个结点
2) 保留结点b的地址
9 SHI 5
0
1
1 ZHAO 2
2 QIAN 3
3 SUN 4
4 LI
9
5 ZHOU 6
6 WU 8
7 ZHENG 8
8 WANG 0
9 SHI 5
i=s[i].cur 指针后移

第九讲 线性表4

第九讲 线性表4

线性表的链式存储结构
• 经过叽叽呱呱的讨论之后,我们派出几个童鞋跟大家 分享一下思路。 • A童鞋:让当中每个元素之间都留有一个空位臵,这 样要插入一个元素时,就不至于要移动了。可一个空 位臵如何解决多个相同位臵插入数据的问题呢?所以 这个想法显然不行。 • B童鞋:那就让当中每个元素之间都留足够多的位臵 ,根据实际情况制定空隙大小,比如每个元素间留10 个空位。那么问题就显而易见了,造成资源的极大浪 费,并且在同一个位臵插入11次也不是不可能。
线性表顺序存储结构的优缺点
• 线性表的顺序存储结构,在存、读数据时,不管 是哪个位臵,时间复杂度都是O(1)。而在插入或 删除时,时间复杂度都是O(n)。 • 这就说明,它比较适合元素个数比较稳定,不经 常插入和删除元素,总结下线性表的顺序存 储结构的优缺点:
线性表顺序存储结构的优缺点
• 优点:
– 无须为表示表中元素之间的逻辑关系而增加额外的 存储空间。 – 可以快速地存取表中任意位臵的元素。
• 缺点:
– 插入和删除操作需要移动大量元素。 – 当线性表长度变化较大时,难以确定存储空间的容 量。 – 容易造成存储空间的“碎片”。
线性表的链式存储结构
• 前面我们讲的线性表的顺序存储结构,它最大的缺点 就是插入和删除时需要移动大量元素,这显然就需要 耗费时间。 • 那我们能不能针对这个缺陷或者说遗憾提出解决的方 法呢?要解决这个问题,我们就得考虑一下导致这个 问题的原因! • 为什么当插入和删除时,就要移动大量的元素? • 原因就在于相邻两元素的存储位臵也具有邻居关系, 它们在内存中的位臵是紧挨着的,中间没有间隙,当 然就无法快速插入和删除。
线性表链式存储结构定义
• 我们把存储数据元素信息的域称为数据域,把存 储直接后继位臵的域称为指针域。指针域中存储 的信息称为指针或链。这两部分信息组成数据元 素称为存储映像,称为结点(Node)。 • n个结点链接成一个链表,即为线性表(a1, a2, a3, …, an)的链式存储结构。 • 因为此链表的每个结点中只包含一个指针域,所 以叫做单链表。

codeblock数据结构算法实现-顺序表基本操作

codeblock数据结构算法实现-顺序表基本操作

数据结构算法实现-顺序表基本操作序号一、引言二、顺序表的定义三、顺序表的基本操作1.初始化操作2.插入操作3.删除操作4.查找操作四、顺序表的实现五、总结一、引言数据结构是计算机科学中非常重要的一部分,它是计算机存储、组织数据的方式。

而顺序表是其中的一种基本数据结构,它采用一组位置区域连续的存储单元依次存放线性表中的元素。

本文将着重介绍顺序表的基本操作及其算法实现。

二、顺序表的定义顺序表是一种基本的线性表,顺序表中元素的逻辑顺序和物理顺序是一致的。

顺序表的特点是利用一组连续的存储单元依次存放线性表中的元素。

顺序表可以用数组实现,其元素在内存中是连续存储的,可以通过下标直接访问元素。

由于顺序表的存储方式,使得其在查找、插入和删除等操作上具有较好的性能。

三、顺序表的基本操作顺序表的基本操作包括初始化、插入、删除和查找等。

下面分别介绍这些操作的实现方法。

1.初始化操作初始化操作是指将一个空的顺序表初始化为一个具有初始容量的顺序表,并为其分配内存空间。

初始化操作的实现方法主要有两种,一种是静态分配内存空间,另一种是动态分配内存空间。

静态分配内存空间时,需要预先指定顺序表的容量大小,然后在程序中创建一个数组,并为其分配指定大小的内存空间。

动态分配内存空间时,可以根据需要动态创建一个数组,并为其分配内存空间。

下面是一个简单的初始化操作的实现示例:```C代码#define MAXSIZE 100 // 定义顺序表的最大容量typedef struct {ElementType data[MAXSIZE]; // 定义顺序表的元素数组int length; // 定义顺序表的当前长度} SeqList;2.插入操作插入操作是指将一个新元素插入到顺序表的指定位置。

插入操作的实现方法主要包括在指定位置插入元素,同时对其他元素进行后移操作。

下面是一个简单的插入操作的实现示例:```C代码Status Insert(SeqList *L, int i, ElementType e) {if (i < 1 || i > L->length + 1) { // 判断插入位置是否合法return ERROR;}if (L->length >= MAXSIZE) { // 判断顺序表是否已满return ERROR;}for (int j = L->length; j >= i; j--) { // 插入位置及之后的元素后移L->data[j] = L->data[j - 1];}L->data[i - 1] = e; // 插入新元素L->length++; // 顺序表长度加1return OK;}```3.删除操作删除操作是指将顺序表中指定位置的元素删除。

线性表

线性表

2.1 线性表的类型定义
例3:下图为10个个学生的成绩表,它也是一个 线性表,该线性表的数据元素类型为结构体类型。
2.1 线性表的类型定义
从以上例子可看出线性表的逻辑特征是: 在非空的线性表中,有且仅有一个被称作 “第一个”的数据元素a1,它没有直接前趋, 而仅有一个直接后继a2; 有且仅有一个被称作“最后一个”的数据元 素an,它没有直接后继,而仅有一个直接前 趋 a n-1; 其余的数据元素ai(2≦i≦n-1)都有且仅有一个 直接前趋a i-1和一个直接后继a i+1。 线性表是一种典型的线性结构。
2.2 线性表的顺序表示和实现
#define MAXNUM 100 Elemtype List1[MAXNUM] ; /*定义线性表L1*/ int length1;
Elemtype List2[MAXNUM] ; /*定义线性表L1*/ int length2;
Elemtype List3[MAXNUM] ; /*定义线性表L1*/ int length3;
2.2 线性表的顺序表示和实现
而只需要将数组和表长封装在一个结构体中,然 后定义三个结构体变量即可: struct L_list { Elemtype List[MAXNUM]; int length; }; struct L_list L1, L2, L3; /*定义三个线性表L1,L2,L3*/
2.1 线性表的类型定义
例1:26个英文字母组成的字母表 (A,B,C、…、Z) 例2:某公司2000年每月产值表(单位:万元) (400,420,500,…,600,650) 是一个长度为12的线性表。

上述两例中的每一个数据元素都是不可分割的, 在一些复杂的线性表中,每一个数据元素又可 以由若干个数据项组成。

数据结构课件第2章线性表

数据结构课件第2章线性表

27
线性表的顺序存储结构适用于数据 元素不经常变动或只需在顺序存取设备 上做成批处理的场合。为了克服线性表 顺序存储结构的缺点,可采用线性表的 链式存储结构。
28
2.3 线性表的链式存储结构
线性表的链式存储表示 基本操作在单链表上的实现 循环链表 双向链表 线性表链式存储结构小结
2.3.1 线性表的链式存储表示 29
2.1.1 线性表的定义
6
一个线性表(linear_list)是 n(n≥0)个具有相同属性的数 据元素的有限序列,其中各元素有着依次相邻的逻辑关系。
线性表中数据元素的个数 n 称为线性表的长度。当 n = 0 时 该线性表称为空表。当 n > 0 时该线性表可以记为:
(a1,a2,a3,…,ai,…,an)
数据域 指针域
结点 data next
31
(2) 线性表的单链表存储结构
通过每个结点的指针域将线性表中 n 个结点按其逻辑顺序链 接在一起的结点序列称为链表,即为线性表 ( a1, a2, a3, …, ai, …, an ) 的链式存储结构。如果线性链表中的每个结点只有一个指针域, 则链表又称为线性链表或单链表 (linked list)。
17
(2) 算法编写
#define OK 1
#define ERROR 0
Int InsList ( SeqList *L, int i, ElemType e ) /*在顺序线性表 L 中第 i 个位置插入新的元素 e。*/ /* i 的合法值为 1≤i ≤L->last+2*/ {
int k; if ( i < 1) ||( i > L->last+2)) /*首先判断插入位置是否合法*/ { printf(“插入位置i值不合法”);

线性表(顺序表)


提示: 1 各算法用函数实现,在主函数中调用这些函数; 2 先从最简单的例子开始
2 插入运算
学号 01 02 03 … 30
成绩 78 90 84 … 83
学号 01 02 03 04 … 31
成绩 78 90 87 84 … 83
下标 插入前 0 1 …
插入x
移动后 a1 a2 … ai-1 ai … an-1 an
插入后 a1 a2 … ai-1 x ai … an-1 an last
最常见的数据组织方式:表格形式的数据
编号 名称 SO2含量 水质指标 悬浮物指标
宗地号
周长
面积
使用者
土地等级
点号
等级
X
Y
H
学号
姓名
性别
籍贯
年龄
成绩
2.1 线性表的基本概念和运算
2.1.1 逻辑结构定义 定义:线性表是由n(n≥0)个数据元素 1,a2,……, 数据元素a 定义:线性 数据元素 an构成的有限序列 有限序列。n为表的长度,n=0时称为空表。 有限序列 非空的线性表(n>0)记作( a1,a2,……,an )。 数据元素可以有不同的含义,但同一线性表中 的元素必须具有相同的特性。
线性表
程序 = 数据结构+算法 线性结构:线性表,栈,队列 数据结构 非线性结构:树,图 数据结构的研究内容: 数据结构的研究内容: • 逻辑结构:数据元素间的客观联系 • 存储结构:数据在计算机内部的存储方法 • 算法研究
在各种程序设计与软件开发中都要涉及到对数 据的组织、存储、管理和处理
在环境领域:不同环境监测点的监测指标统计 在土地领域:不同宗地的属性 在测绘领域:外业测绘信息的存储,各测点三维坐 标的存储

吉林大学数据结构_第二章 线性表


如何找指定位置的结点?
• 与顺序表不同,单链表无法直接访问指定 位置的结点,而是需要从哨位结点开始, 沿着next指针逐个结点计数,直至到达指定 位置。
操作
• • • • 存取 查找 删除 插入
存取算法
算法Find(k.item) /*将链表中第k个结点的字段值赋给item*/ F1. [k合法?] IF (k<1) THEN (PRINT “存取位置不合法”. RETURN.) F2. [初始化] p←head. i ←0. F3. [找第k个结点] WHILE (p ≠NULL AND i<k) DO (p←next(p). i ←i+1.) IF p=NULL THEN (PRINT “无此结点”. RETURN. ) item←data(p). ▍ 存取算法的时间复杂性分析。P30
插入算法
算法Insert(k,item) /*在链表中第k个结点后插入字段值为item的结点*/ I1.[k合法?] IF (k<0) THEN (PRINT “插入不合法”. RETURN) I2.[初始化] p←head. i ←0. I3.[p指向第k个结点] WHILE (p ≠NULL AND i<k) DO (p←next(p). i ←i+1.) IF p=NULL THEN (PRINT “插入不合法”. RETURN. ) I4.[插入] s<= AVAIL. data(s) ←item. next(s) ←next(p). next(p) ←s. ▍
删除算法
算法Delete(k.item) /*删除链表中第k个结点并将其字段值赋给item*/ D1.[k合法?] IF (k<1) THEN (PRINT “删除不合法”. RETURN.) D2.[初始化] p←head. i ←0. D3.[找第k-1结点] WHILE (p ≠NULL AND i<k-1) DO (p←next(p). i ←i+1.) IF p=NULL THEN (PRINT “无此结点”. RETURN. ) D4.[删除] q ← next(p). next(p) ← next(q) . item←data(q). AVAIL<=q.▍

数据结构-顺序表

数据结构-顺序表判断题1.(neuDS)所谓随机存取,就是通过⾸地址和元素的位序号值可以在O(1)的时间内找到指定的元素。

F2.(neuDS)在顺序表上进⾏插⼊、删除操作时需要移动元素的个数与待插⼊或待删除元素的位置⽆关。

T F3.顺序存储⽅式只能⽤于存储线性结构。

T F4.在顺序表中取出第i个元素所花费的时间与i成正⽐。

T F5.对于顺序存储的长度为N的线性表,删除第⼀个元素和插⼊最后⼀个元素的时间复杂度分别对应为O(1)和O(N)。

T F6.(neuDS)在顺序表中逻辑上相邻的元素,其对应的物理位置也是相邻的。

F7.顺序存储的线性表可以随机存取。

F8.顺序存储结构的主要缺点是不利于插⼊或删除操作。

F选择题1.⽤数组表⽰线性表的优点是()。

A.便于插⼊和删除操作B.便于随机存取C.可以动态地分配存储空间D.不需要占⽤⼀⽚相邻的存储空间2.阅读下列程序,其功能是()。

typedef struct {ElemType *list;int size;intMaxSize;}SeqList;void fun1(SeqList&L) {inti, j;ElemType temp;for (i=0, j= L.sise-1; i<j; i++, j--) {temp=L.list[i];L.list[i]=L.list[j];L.list[j]=temp;}}A.将顺序表原地逆置B.将链表原地逆置C.将顺序表⾸尾元素对换D.将链表⾸尾元素对换3.顺序存储表⽰中数据元素之间的逻辑关系是由()表⽰的。

A.指针B.逻辑顺序C.存储位置D.问题上下⽂4.顺序表的优点是()。

A.插⼊操作的时间效率⾼B.适⽤于各种逻辑结构的存储表⽰C.存储密度(存储利⽤率)⾼D.删除操作的时间效率⾼5.若线性表最常⽤的操作是存取第i个元素及其前驱的值,则采⽤( )存储⽅式节省时间。

A.单链表B.双向链表C.单循环链表D.顺序表6.数组A[1..5,1..6]每个元素占5个单元,将其按⾏优先次序存储在起始地址为1000的连续的内存单元中,则元素A[5,5]的地址为:A.1120B.1125C.1140D.11457.若某线性表最常⽤的操作是存取任⼀指定序号的元素和在最后进⾏插⼊和删除运算,则利⽤哪种存储⽅式最节省时间?A.双链表B.单循环链表C.带头结点的双循环链表D.顺序表8.若长度为n的线性表采⽤顺序结构,在第i个数据元素之前插⼊⼀个元素,需要它依次向后移动()个元素。

数据结构-线性结构

数据结构-线性结构线性表线性表是最简单最常见的数据结构,属于逻辑结构;线性表有两种实现⽅式(存储⽅式),分别是顺序实现和链接实现;定义:线性表是由n(>=0)个数据元素组成的有限序列,数据元素的个数n定义为表的长度;术语:前驱, 后继, 直接前驱, 直接后继, 长度, 空表案例:线性表⽤L表⽰,⼀个⾮空线性表可记为L = (a1,a2,..an);a1后⾯的称为a1的后继an前⾯的称为an的前驱a1为起始节点,an为终端节点,任意相邻的两个元素,如a1和a2,a1是a2的直接前驱,a2是a1的直接后继;线性表中元素个数即表的长度,此处为n;表中没有任何元素时,称为空表除了⾸节点和尾节点之外,每个节点都有且只有⼀个直接前驱和直接后继,⾸节点没有前驱,尾节点没有后继;节点之间的关系属于⼀对⼀;线性表的基本运算初始化Initiate(L) 建⽴⼀个空表L(),L不包含数据元素求表长度Length(L) 返回线性表的长度取表元素Get(L,i) 返回线性表的第i个元素,i不满⾜1<=i<=Length(L)时,返回特殊值;定位Locate(L,x)查找x在L中的节点序号,若有多个匹配的返回第⼀个,若没有匹配的返回0;插⼊Insert(L,x,i)将x插⼊到L的第i个元素的前⾯(其他元素往后挪),参数i取值范围为1<=i<=Length(L)+1;运算结束后表长度+1;删除Delete(L,i)删除表L中的第i个元素,i有效范围1<=i<=Length(L);操作结束后表长度-1强调:上述的第i个指的是元素的序号从1开始,⽽不是下标从0开始;另外:插⼊操作要保证操作后数据还是⼀个接着⼀个的不能出现空缺;线性表的顺序存储实现线性表是⼀种逻辑结构,可以通过顺序存储结构来实现,即:将表中的节点⼀次存放在计算机内存中⼀组连续的存储单元中,数据元素在线性表中的邻接关系决定了它们在存储空间中的存储位置;换句话说逻辑结构中相邻的两个节点的实际存储位置也相邻;⽤顺序存储结构实现的线性表也称之为为顺序表,⼀般采⽤数组来实现;图⽰:⼤⼩与长度:线性表的⼤⼩:指的是最⼤能存储的元素个数线性表的长度:指的是当前已存储的个数⽰例:c语⾔实现:#include <stdio.h>//初始化操作:const MAX_SIZE = 5;//最⼤长度typedef struct list {int data[MAX_SIZE];//数组int length;//当前数据长度};//获取targert在表中的位置int locate(struct list *l,int target){for (int i = 0;i < l->length;i++){if (target == l->data[i]){return i + 1;}}return 0;}//获取第loc个元素int get(struct list *l,int loc){if (loc < 1 || loc > l->length){printf("error:位置超出范围\n");return -1;}else{return l->data[loc-1];}}//插⼊⼀个元素到第loc个位置上void insert(struct list *l,int data,int location){if (l->length == MAX_SIZE){printf("errolr:表容量已满\n");return;}if (location < 1 || location > l->length+1){printf("error:位置超出范围\n");return;}//⽬标位置后⾯的内容以此往后挪for (int i = l->length; i >= location; i--) {l->data[i] = l->data[i-1];}//在⽬标位置放⼊新的数据l->data[location-1] = data;l->length+=1;//长度加1}//删除第loc个元素,从⽬标位置往后的元素⼀次向前移动void delete(struct list *l,int loc){if (loc < 1|| loc > l->length){printf("error:位置超出范围\n");return;}//⽬标位置及后⾯的所有元素全部向后移动for (;loc < l->length; ++loc) {l->data[loc-1] = l->data[loc];}l->length-=1;}//打印所有元素测试⽤void show(struct list l){for (int i = 0; i < l.length; ++i) {printf("%d\n",l.data[i]);}}//测试int main() {struct list alist = {};insert(&alist,100,alist.length+1);insert(&alist,200,alist.length+1);insert(&alist,300,alist.length+1);insert(&alist,400,alist.length+1);delete(&alist,1);printf("%d\n",alist.length);show(alist);printf("%d\n",get(&alist,4));printf("%d\n", locate(&alist,300));printf("%d\n", get(&alist,1));return 0;}插⼊算法分析:假设线性表中含有n个元素,在插⼊元素时,有n+1个位置可以插⼊,因为要保证数据是连续的每个位置插⼊数据的概率是: 1/(n+1)在i的位置插⼊时,要移动的元素个数为:n - i + 1算法时间复杂度为:O(n)删除算法分析:假设线性表中含有n个元素,在删除元素时,有n个位置可以删除每个位置插⼊数据的概率是: 1/n在i的位置删除时,要移动的元素个数为:n - i算法时间复杂度为:O(n)插⼊与删除的不⾜顺序表在进⾏插⼊和删除操作时,平均要移动⼤约⼀半的数据元素,当存储的数据量⾮常⼤的时候,这⼀点需要特别注意;简单的说,顺序表在插⼊和删除时的效率是不够好的;特别在数据量⼤的情况下;顺序表总结:1.顺序表是⼀维数组实现的线性表2.逻辑上相邻的元素,在存储结构中也是相邻的3.顺序表可实现随机读取优缺点:优点:⽆需为了表⽰元素直接的逻辑关系⽽增加额外的存储空间可⽅便的随机存取表中的任⼀节点缺点:插⼊和删除运算不⽅便,需要移动⼤量的节点顺序表要求占⽤连续的存储空间,必须预先分配内存,因此当表中长度变化较⼤时,难以确定合适的存储空间⼤⼩;顺序表节点存储地址计算:设第i个节点的存储地址为x设顺序表起始地址为loc,每个数据元素占L个存储单位计算公式为:x = loc + L * (i-1)如 loc = 100 i = 5 L = 4 则 x = 116线性表的链接存储实现线性表也可通过链接存储⽅式来实现,⽤链接存储⽅式实现的线性表也称为链表 Link List链式存储结构:1.可⽤任意⼀组存储单元来存储数据2.链表中节点的逻辑次序与物理次序不⼀定相同3.每个节点必须存储其后继节点的地址信息(指针)图⽰:单链表单链表指的是只能沿⼀个⽅向查找数据的链表,如上图每个节点由两个部分(也称为域)组成data域存放节点值得数据域next域存放节点的直接后继的地址的指针域(也称为链域)节点结构:每个节点只知道⾃⼰后⾯⼀个节点却不知道⾃⼰前⾯的节点所以称为单链表图⽰:带有head节点的单链表:单链表的第⼀个节点通常不存储数据,称为头指针,使⽤头指针来存储该节点的地址信息,之所以这么设计是为了⽅便运算;单链表特点:其实节点也称为⾸节点,没有前驱,所以头指针要指向该节点,以保证能够访问到起始节点;头指针可以唯⼀确定⼀个链表,单链表可以使⽤头指针的名称来命名;终端节点也称尾节点,没有后继节点,所以终端节点的next域为NULL;除头结点之外的⼏点称为表结点为⽅便运算,头结点中不存储数据单链表数据结构定义//数据结构定义typedef struct node {struct node *next;int data,length;} Node, *LinkList;/** typedef 是⽤来取别名的* Node 是struct node 的别名* *LinkList 是 struct node *的别名* 后续使⽤就不⽤在写struct关键字了*/运算:初始化⼀个空链表有⼀个头指针和⼀个头结点构成假设已定义指针变量L,使L指向⼀个头结点,并使头结点的next为NULL//时间复杂度 :O(1)LinkList initialLinkList() {// 定义链表的头结点LinkList head;//申请空间head = malloc(sizeof(struct node));//使头结点指向NULLhead->next = NULL;return head;}求表长从头指针开始遍历每个节点知道某个节点next为NULL为⽌,next不为空则个数len+1;//求表长时间复杂度 :O(n)int length(LinkList list){int len = 0;Node *c = list->next;while(c != NULL){len+=1;c = c->next;}return len;}读表元素给定⼀个位置n,获取该位置的节点遍历链表,过程中若某节点next为NULL或已遍历个数index=n则结束循环//从链表中获取第position个位置的节点时间复杂度 :O(n)Node *get(LinkList list, int position) {Node *current;int index = 1;current = list->next;//如果下⾯还有值并且还没有到达指定的位置就继续遍历要和查找元素区别开这就是⼀直往后遍历直到位置匹配就⾏了 while (current != NULL && index < position) {current = current->next;index += 1;}if (index == position) {return current;}return NULL;}定位对给定表元素的值,找出这个元素的位置遍历链表,若某节点数据域与要查找的元素data相等则返回当前遍历的次数index//求表head中第⼀个值等于x的结点的序号(从1开始),若不存在这种结点,返回结果为0 时间复杂度 :O(n)int locate(LinkList list,int data){int index = 1;Node *c;c = list->next;while (c != NULL){if (c->data == data){return index;}index+=1;c = c->next;}return 0;}插⼊在表的第i个数据元素结点之前插⼊⼀个以x为值的新结点new获取第i的节点的直接前驱节点pre(若存在),使new.next = pre.next;pre.next = new;//在表head的第i个数据元素结点之前插⼊⼀个以x为值的新结点时间复杂度 :O(n)void insert(LinkList list, int position, int data) {Node *pre, *new;if (position == 1) {//若插⼊位置为1 则表⽰要插⼊到表的最前⾯即head的后⾯pre = list;} else {//pre表⽰⽬标位置的前⼀个元素所以-1pre = get(list, position - 1);if (pre == NULL) {printf("error:插⼊的位置超出范围");exit(0);}}new = malloc(sizeof(Node));new->data = data;new->next = pre->next;pre->next = new;list->length += 1;}删除删除给定位置的节点获取⽬标节点target的直接前驱节点pre(若pre与⽬标都有效),pre.next = target.next; free(target);//删除链表中第position个位置的节点时间复杂度 :O(n)void delete(LinkList list,int position){//获取要删除节点的直接前驱Node *pre;if (position == 1){ //如要删除的节点是第⼀个那直接前驱就是头结点pre = list;}else{pre = get(list,position-1);}////如果⽬标和前驱都存在则执⾏删除if (pre != NULL && pre->next != NULL){Node *target = pre->next; //要删除的⽬标节点//直接前驱的next指向⽬标的直接后继的nextpre->next = target->next;free(target);printf("info: %d被删除\n",target->data);list->length -= 1;}else{printf("error:删除的位置不正确!");exit(1);}}创建具备指定数据节点的链表//效率⽐较差算法时间复杂度 :O(n^2)LinkList createLinkList1(){LinkList list = initialLinkList();int a;//输⼊的数据int index = 1; //记录当前位置scanf("%d",&a);while (a != -1){ // O(n)insert(list,index++,a); // O(n^2) 每次都要从头遍历链表scanf("%d",&a);}return list;}//尾插算法记录尾节点从⽽避免遍历时间复杂度 :O(n)LinkList createLinkList2(){LinkList list = initialLinkList();int a;//输⼊的数据Node *tail = list;//当前的尾部节点scanf("%d",&a);while (a != -1){ // O(n)Node * newNode = malloc(sizeof(Node)); //新节点newNode->next = NULL;newNode->data = a;tail->next = newNode;//尾部节点的next指向新节点tail = newNode;//新节点作为尾部节点scanf("%d",&a);}return list;}//头插算法每次插到head的后⾯,不⽤遍历但是顺序与插⼊时相反时间复杂度 :O(n)LinkList createLinkList3(){LinkList list = initialLinkList();int a;//输⼊的数据Node * head = list;scanf("%d",&a);while (a != -1){ // O(n)Node * newNode = malloc(sizeof(Node)); //新节点newNode->next = NULL;newNode->data = a;newNode->next = head->next;//将原本head的next 交给新节点;head->next = newNode;//在把新节点作为head的next;scanf("%d",&a);}return list;}优缺点优点:在⾮终端节点插⼊删除时⽆需移动其他元素⽆需预分配空间,⼤⼩没有限制(内存够的情况)缺点:⽆法随机存取读取数据慢链表与顺序表的对⽐:操作顺序表链表读表元O(1)O(n)定位O(n)O(n)插⼊O(n)O(n)删除O(n)O(n)。

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

线性表顺序存储结构算法的实现
说明:将顺序表以及在该存储结构上线性表的基本操作自定义成类Seqlist如
下:
class Seqlist
{int maxsize;//顺序表的最大容量
int[] data;//用于存储顺序表中的数据元素
int length;//顺序表的实际数据元素的个数
InitList(int size) //初始化顺序表
IsFull()断顺序表是否满
IsEmpty()//判断顺序表是否空
AddNode(int a) //在顺序表的末尾追加数据元素
DeleteNode(int i) //删除顺序表中的第i个数据
SearchNode(int value) //在顺序表中查找值为value的第一个数据元素的
位置
Getlength()//求顺序表的实际长度
Clear()//清空顺序表
}
然后在主函数中去验证这些算法。
具体代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Slinelist
{public class Seqlist
{
public int maxsize;//顺序表的最大容量
public int[] data;//用于存储顺序表中的数据元素
public int length;//顺序表的实际数据元素的个数

//初始化顺序表
public void InitList(int size)
{
maxsize = size;
data = new int[maxsize];
length = 0;
}
//判断顺序表是否满
public bool IsFull()
{
if (length == maxsize) return true;
else return false;
}
//判断顺序表是否空
public bool IsEmpty()
{
if (length == 0) return true;
else return false;
}

//在顺序表的末尾追加数据元素
public void AddNode(int a)
{
if (IsFull())
{
Console.WriteLine("List is full");
return;
}
data[length] = a;
length++;
}

//在顺序表中的第i个位置插入一个数据元素a
public void InterNode(int a, int i)
{
if (IsFull())
{
Console.WriteLine("List is full");
return;
}
if (i < 1 || i > length + 1)
{
Console.WriteLine("Position is error");
return;
}
else
{
for (int j = length - 1; j >= i - 1; j--)
data[j + 1] = data[j];
data[i - 1] = a;
length++;
}

}
//删除顺序表中的第i个数据
public void DeleteNode(int i)
{
if (IsEmpty())
{ Console.WriteLine("List is empty");
return;
}
if (i < 1 || i > length)
{
Console.WriteLine("Position is error!");
return;
}
else
{
for (int j = i; j < length; j++)
data[j - 1] = data[j];
length--;
}
}

//获得顺序表的第i个数据元素
public int PrintNode(int i)
{
if (IsEmpty() || (i < 1) || (i > length))
{
Console.WriteLine("List is empty or Position is error!");
return -1;
}
return data[i - 1];
}

//在顺序表中查找值为value的第一个数据元素的位置
public int SearchNode(int value)
{
int j;
if (IsEmpty())
{ Console.WriteLine("List is empty!");
return -1;
}
for (j = 0; j < length; j++)
if (data[j] == value) break;
if (j >= length) return -1;
else return j + 1;
}
//求顺序表的实际长度
public int Getlength()
{ return length; }
//清空顺序表
public void Clear()
{
length = 0;
}
}

class Program
{
static void Main(string[] args)
{
Seqlist s_list = new Seqlist();
s_list.InitList(10);
int key, index;
int counter = 0;

//插入算法的验证
do
{
Console.WriteLine("请输入插入的数据:");
key = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请输入插入数据的位置:");
index = Convert.ToInt32(Console.ReadLine());
s_list.InterNode(key, index);
counter++;
} while (counter < 4);
Console.WriteLine("输出插入数据后顺序表中的数据:");
for (int j = 0; j < s_list.length; j++)
{ Console.Write("{0} ", s_list.data[j]); }

//删除算法的验证
Console.WriteLine("请输入删除数据的位置:");
index = Convert.ToInt32(Console.ReadLine());
s_list.DeleteNode(index);
Console.WriteLine("输出删除数据后顺序表中的数据:");
for (int j = 0; j < s_list.length; j++)
{ Console.Write("{0} ", s_list.data[j]); }

//查找算法的验证
Console.WriteLine("请输入查找的数据:");
key= Convert.ToInt32(Console.ReadLine());
Console.WriteLine ("所查找的数据位置是{0}",s_list.SearchNode(key));
Console.WriteLine("顺序表的实际长度为{0}",s_list.Getlength ());
Console.ReadLine();
}
}
}

相关文档
最新文档