数据结构线性表
b +(i-1)L
b +(n-1)L
a1
L1
顺
a2
2
序
……
随表
ai ai+1 ……
i
机中
存的
取元
。素
an
n
可
空闲区
以
8
例1 一个一维数组M,下标的范围是0到9,每
个数组元素用相邻的5个字节存储。存储器按字 节编址,设存储数组元素M[0]的第一个字节的地
址是98,则M[3]的第一个字节的地址是 113
应当有1≤i≤L.length
18
删除顺序表的第i个结点L.data[i-1]
SeqList DeleteList(SeqList L, int i){
int j; if(i<1||i>L.length)
{ printf(“position error!\n”); exit(0); }
for(j=i; j<=L.length-1; j++)
需特殊处理; 空表:head==NULL; 非空表:r->next==NULL;
2.空表与非空链表处理不一致。
34
可在单链表的第一个结点之前附设一个结点,称之 为头结点,解决上述复杂性。示意图如下:
head
info
a1
a2
…
an ^
头指针 头结点 首元结点
空链表: head info ^
35
思考:带头结点的链表的优越性
}
29
以下为在已有链表中插入、删除结点的函数。 “C语言复习”中讲过,不详述。 不同之处:查找方式不同。 ➢ 按值查找插入删除结点的位置; ➢ 按序号查找插入删除结点的位置;
30
ListNode *del(ListNode *head, int i){
ListNode *p,*q; int j=1; p=head;
while( j<i && p!=NULL ){
q=p; p=p->next; j=j+1 ; }
if(j==i){
if(i==1) head=p->next ;
else q->next=p->next ;
(*)
printf("The No. %dth char is deleted\n",i); }
应有1≤i≤ L.length+1 L.length < ListSize
15
将新结点x插入顺序表的第i个结点L.data[i-1]的位置上
SeqList InsertList(SeqList L, int x, int i){
int j; if(i<1||i>L.length+1)
{ printf(“position error!\n”); exit(0); }
于春梅 何仕鹏 王爽 王亚武
:
:
性别
女 男 女 男 :
年龄
18 18 18 18 :
班级
2001级电信016班 2001级电信017班 2001级通信011班 2001级通信012班
:
数据元素都是记录; 元素间关系是线性
5
2.2 顺序表
2.2.1 顺序表的表示(*)
2.2.2 对顺序表操作的实现 2.2.3 顺序表的运算效率分析 本节小结
6
2.2.1 顺序表的表示 线性表的顺序存储结构。 把线性表的结点按逻辑次序依次存放在一组地 址连续的存储单元里。用这种方法存储的线性 表简称为顺序表。
简言之,逻辑上相邻,物理上也相邻
高级语言中实现方法: (一维)数组 V[n]
7
线性表的顺序存储结构示意图
地址
内容
元素在表中的位序
b=LOC(a1) b+L
的核心语句:
head=s;
从空表开始,若读入的字符不为‘\n’,就将 新结点s链到表头。
26
ListNode *CreateListF(){ char ch; ListNode *head,*s; head=NULL; while((ch=getchar())!='\n'){ s=(ListNode *)malloc(sizeof(ListNode)); s->data=ch; s->next=head; head=s; } return head;
数据元素
表头元素
下标:是元素的 序号,表示元素 在表中的位置
ai的直接前趋 ai的直接后继 表尾元素
n=0时称为 空表
n为元素总个 数,即表长
线性表的逻辑结构示意图
3
线性表的特点:(若非空)
(1)存在唯一一个被称作“第一个”的数据元素; (2)存在唯一一个被称作“最后一个”的数据元素; (3)除第一个元素,每个元素均只有一个前驱; (4)除最后一个元素,每个元素均只有一个后继;
解:地址计算通式为: LOC(ai) = LOC(a1) + L *(i-1)
因此:LOC( M[3] ) = 98 + 5 ×(3-0) =113
9
顺序表结构定义
(*)
用一维数组来存放表结点
#define ListSize 100 //表空间的大小,假设为100
typedef struct L{
L.data[j-1]=L.data[j];
L.length--;
return L;
}
19
2.2.3 顺序表的运算效率分析 时间效率分析:
算法时间主要耗费在移动元素的操作上
讨论1:若在长度为 n 的线性表的第 i 位前 插入一 元素则向后移动元素的次数f(n)为:
f(n) = n – i + 1
讨论2:若在长度为n的线性表上删除第i位元素, 向前移动元素的次数f(n)为:
int data[ListSize]; int length; }SeqList;
void main(){ SeqList L; L.length=0;
}
12
查找结点
顺序表L中第i个节点如何表示?
L.data[i-1]
13
数组下标 内存 元素序号
0
a1 1
1
a2 2
数组下标 内存 元素序号
0
a1 1
数据结构课程的内容
唯一的逻辑结构 对应
不唯一的存储结构
运算的实现依赖于 存储结构
1
第2章 线性表
2.1 线性表的类型定义(逻辑结构)
2.2 顺序表(*) 2.3 链 表(*)
2.4 应用举例
2
2.1 线性表的类型定义
线性表:是由n(n>=0)个数据元素(结点)a1,a2…an
组成的有限序列。
(a1, a2, … ai-1,ai, ai+1 ,…, an)
链式存储结构
见2.3节
22
2.3 线性表的链式表示和实现
2.3.1 链表的表示(*)
2.3.2 链表的实现(*)
2.3.3 链表的运算效率分析 2.3.4 应用举例
23
2.3.1 链表的表示
链式存储结构特点:逻辑上相邻的两个数据 元素,物理上不一定相邻。
用C语言描述的单链表如下:
typedef struct Lnode {
char
data;
struct Lnode *next;
}ListNode;
//数据域 //指针域
24
2.3.2 链表的实现
1. 单链表的建立和输出(*) 2. 删除单链表中结点(*) 3. 在单链表中插入结点(*)
4. 其它链表形式
25
建立单链表:(1)头插法建表
方法:
hea/d/ c
b
a^
s d 有关指针操作 s->next=head;
}
27
2.尾插法建表
head
a
b
新结点插到表尾,必须增 加尾指针r,使其始终指向 当前表尾结点;
c
// r
s
d^
核心语句: if(head==NULL)
head=s; else
r->next=s; r=s;
28
ListNode *CreateListR(){ char ch; ListNode *head,*s,*r; head=r=NULL; while((ch=getchar())!='\n'){ s=(ListNode *)malloc(sizeof(ListNode)); s->data=ch; s->next=NULL; if(head==NULL) head=s; else r->next=s; r=s; } return head;
0
a1 1
1
a2 2
V数组下标 内存 元素序号
0
a1 1
1
a2 2
i-1 ai i
i
ai+1 i+1
n-1 an n=L.length
i-1 ai+1 i i ai+2 i+1
n-2 an n-1
n-1
n
删除:删除顺序表L中第i个位置的元素 17
3)删除 删除线性表的第i个位置上的元素 实现步骤: • 将第i +1至第n 位的元素向前移动一个位置; • 表长减1。 注意:事先需要判断,删除位置i 是否合法?
if(head==NULL){ head=s ; s->next=NULL ; }
else{ while(( j<i )&&( p!=NULL )){
q=p; p=p->next; j++; }