1、什么是线性表?
线性表(Linear List):由同类型元素构成有序序列的线性结构。
表中元素个数称为线性表的长度
线性表没有元素时,称为空表
表起始位置称表头,表结束位置称为表尾
2、线性表的抽象数据类型描述
List MakeEmpty():初始化一个空线性表L;
ElementType FindKth( int K, List L ):根据位序K,返回相应元素 ;
ElementType FindKth( int K, List L ):根据位序K,返回相应元素 ;
int Find( ElementType X, List L ):在线性表L中查找X的第一次出现位置;
void Insert( ElementType X, int i, List L):在位序i前插入一个新元素X;
void Delete( int i, List L ):删除指定位序i的元素;
int Length( List L ):返回线性表L的长度n。
3、主要实现方式:顺序存储实现和链式存储实现
4、线性表的顺序存储实现
(1)如何存储
1
2
3
4
5
6
7
|
//如何存储
typedef
struct
{
ElementType Data[MAXSIZE];
int
Last;
}List;
List L,*PtrL;
|
访问下标为i的元素:L.Data[i]或PtrL->Data[i]
线性表的长度:L.Last+1或者PtrL->Last+1
(2)初始化(建立空的顺序表)
1
2
3
4
5
6
7
|
List *MakeEmpty()
{
List *PtrL;
PtrL = (List *)
malloc
(
sizeof
(List));
PtrL->Last = -1;
return
PtrL;
}
|
(3)查找
1
2
3
4
5
6
7
8
9
10
11
12
13
|
int
Find(ElementType X, List *PtrL)
{
int
i = 0;
while
(i <= PtrL->Last && PtrL->Data[i]!=X)
i++;
if
(i > PtrL->Last)
{
return
-1;
}
else
{
return
i;
}
}
|
查找成功的平均比较次数为(n+1)/ 2(第一次比较就找到或者最后一次比较才找到),平均时间性能为O(n)。
(4)插入(第i(1<=i<=n+1)个位置上插入一个值为X的新元素)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//插入
void
Insert(ElementType X,
int
i,List *PtrL)
{
int
j;
if
(PtrL->Last==MAXSIZE-1)
{
printf
(
"表满"
);
return
;
}
if
(i < 1 || PtrL->Last+2)
{
printf
(
"位置不合法"
);
return
;
}
for
(j = PtrL->Last; j >= i-1; --j)
{
PtrL->Data[j+1]=PtrL->Data[j];
//将ai~an倒序向后移动
}
PtrL->Data[i-1] = X;
//插入新元素
PtrL->Last++;
//Last仍指向最后元素
return
;
}
|
平均移动次数为n/2,平均时间性能为O(n)。
(5)删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//删除
void
Delete(
int
i,List *PtrL)
{
int
j;
if
(i < 1 || i >PtrL->Last+1)
{
printf
(
"不存在第%d个元素"
,i );
return
;
}
for
(j = i; j <= PtrL->Last;++j)
{
PtrL->Data[j-1]=PtrL->Data[j];
//将ai+1~an顺序向前移动
}
PtrL->Last--;
return
;
}
|
平均移动次数为(n-1)/2,平均时间性能为O(n)。
5、线性表的链式存储实现
不要求逻辑上相邻的两个元素物理上也相邻;通过“链”建立起数据元素之间的逻辑关系
插入、删除不需要移动数据元素,只需要修改“链”。
(1)如何存储
1
2
3
4
5
6
7
|
//如何存储
typedef
struct
Node
{
ElementType Data;
struct
Node *Next;
}List;
List L,*PtrL;
|
(2)求表长
1
2
3
4
5
6
7
8
9
10
11
12
|
//求表长
int
Length(List *PtrL)
{
List *p = PtrL;
//p指向表的第一个结点
int
j = 0;
while
(p)
{
p = p->Next;
//当前p指向第j个结点
j++;
}
return
j;
}
|
(3)查找
按照序号查找:FindKth
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
List *FindKth(
int
K,List *PtrL)
{
List *p = PtrL;
int
i = 1;
while
(p != NULL&&i < k)
{
p = p->Next;
i++;
}
if
(i==k)
{
return
p;
//找到第K个,返回指针
}
else
{
return
NULL;
}
}
|
按照值查找:Find
1
2
3
4
5
6
7
8
9
10
|
List *Find(ElementType X,List *PtrL)
{
List *p = PtrL;
while
(p != NULL && p->Data != X)
{
p = p->Next;
}
return
p;
}
|
(4)插入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
List *Insert(ElementType X,
int
i, List *PtrL)
{
List *p,*s;
if
(i == 1)
//新结点插入在表头
{
s = (List *)
malloc
(
sizeof
(List));
s->Data = X;
s->Next = PtrL;
return
s;
}
p = FindKth(i-1,PtrL);
if
(p == NULL)
{
printf
(
"参数i错误"
);
//第i-1个元素不存在,则不能插入
return
NULL;
}
else
{
s = (List *)
malloc
(
sizeof
(List));
s->Data = X;
s->Next = p->Next;
//新结点插入在第i-1个结点的后面
p->Next = s;
return
PtrL;
}
}
|
(5)删除(删除链表的第i(1<=i<=n)个位置上的结点)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
List *Delete(
int
i,List *PtrL)
{
List *p,*s;
if
(i == 1)
//删除的结点是第一个结点
{
s = PtrL;
//s指向第一个结点
if
(PtrL!=NULL)
{
PtrL = PtrL->Next;
//从链表中删除
}
else
{
return
NULL;
}
free
(s);
return
PtrL;
}
P = FindKth(i-1, PtrL);
//查找第i-1个结点
if
(p == NULL)
{
printf
(
"第%d个结点不存在"
,i-1);
return
NULL;
}
else
if
(p->Next==NULL)
{
printf
(
"第%d个结点不存在"
,i );
return
NULL;
}
else
{
s = p->Next;
//s指向第i个结点
p->Next = s->Next;
//从链表中删除
free
(s)
return
PtrL;
}
}
|