线性表之顺序表
线性表
1、线性表是包含若干数据元素的一个线性序列。记为:
L
=
(
a
0
,
.
.
.
.
.
.
a
i
−
1
,
a
i
,
a
i
+
1
,
.
.
.
.
.
.
a
n
−
1
)
L
为表名,
a
i
(
0
≤
i
≤
n
−
1
)
为数据元素;
n
为表长,
n
≥
0
时,线性表
L
为非空表,否则为空表。
L=(a_0,......a_{i-1},a_i,a_{i+1},......a_{n-1}) \\L为表名,a_i(0\leq i \leq n-1)为数据元素; \\n为表长,n\geq 0时,线性表L为非空表,否则为空表。
L=(a0,......ai−1,ai,ai+1,......an−1)L为表名,ai(0≤i≤n−1)为数据元素;n为表长,n≥0时,线性表L为非空表,否则为空表。
线性表L可用二元组形式描述:L=(D,R);即Data,Relation。
即线性表L包含数据元素集合D和关系集合R。
D
=
{
a
i
∣
a
i
∈
d
a
t
a
t
y
p
e
,
i
=
0
,
1
,
2
⋅
⋅
⋅
⋅
⋅
⋅
n
−
1
,
n
≥
0
}
R
=
{
a
i
,
a
i
+
1
>
∣
a
i
,
a
i
+
1
∈
D
,
0
≤
i
≤
n
−
2
}
D=\{ a_i|a_i∈datatype,i=0,1,2······n-1,n\geq0\}\\ R=\{ a_i,a_{i+1}>|a_i,a_{i+1}∈D,0\leq i \leq n-2\}
D={ai∣ai∈datatype,i=0,1,2⋅⋅⋅⋅⋅⋅n−1,n≥0}R={ai,ai+1>∣ai,ai+1∈D,0≤i≤n−2}
关系符
<
a
i
,
a
i
+
1
>
<a_i,a_{i+1}>
<ai,ai+1>在这里称为有序对
表示任意相邻的两元素之间的一种先后次序关系。
a
i
a_i
ai是
a
i
+
1
a_{i+1}
ai+1的直接前驱,
a
i
+
1
a_{i+1}
ai+1是
a
i
a_i
ai的直接后继。
2、线性表的特征
- 对非空表, a 0 a_0 a0是表头,无前驱;
- a n − 1 a_{n-1} an−1是表尾,无后继;
- 其它的每个元素 a i a_i ai有且仅有一个直接前驱 a i − 1 a_{i-1} ai−1和一个直接后继 a i + 1 a_{i+1} ai+1。
线性表顺序存储
1、顺序存储结构的表示
若将线性表 L = ( a 0 , a 1 , … … , a n − 1 ) L=(a_0,a_1, ……,a_{n-1}) L=(a0,a1,……,an−1)中的各元素依次存储于计算机一片连续的存储空间。
2、顺序存储结构的特点
- 逻辑上相邻的元素 a i , a i + 1 a_i, a_{i+1} ai,ai+1,其存储位置也是相邻的。
- 对数据元素 a i a_i ai的存取为随机存取或按地址存取。
- 存储密度高:存储密度D=(数据结构中元素所占存储空间)/(整个数据结构所占空间)。
3、顺序存储结构的不足
- 对表的插入和删除等运算的时间复杂度较差。
应用场景:在C语言中,可以借助一维数组类型来描述线性表的顺序存储结构。如:
//线性表的顺序存储结构
#define N 100
typedef int data_t;
typedef struct
{ data_t data[N]; //表的存储空间
int last;
} sqlist, *sqlink;
设计功能
1、线性表的基本运算
设线性表 L = ( a 0 , a 1 , … … , a n − 1 ) L=(a_0,a_1, ……,a_{n-1}) L=(a0,a1,……,an−1),对 L的基本运算有:
1)建立一个空表:list_create(L)
2)置空表:list_clear(L)
3)判断表是否为空:list_empty (L)。若表为空,返回值为1 , 否则返回 0
4)求表长:length (L)
5)取表中某个元素:GetList(L , i ), 即 a i a_i ai。要求0≤i≤length(L)-1
6)定位运算:Locate(L,x)。确定元素x在表L中的位置(或序号)
L
o
c
a
t
e
(
L
,
x
)
=
{
i
当元素
x
=
a
i
∈
L
,
且
a
i
是第一个与
x
相等时;
−
1
x
不属于
L
时。
Locate(L,x)= \left\{ \begin{array}{l} i~~~~~~~~当元素x=ai∈L,且ai是第一个与x相等时;\\ -1 ~~~~~ x不属于L时。 \end{array} \right.
Locate(L,x)={i 当元素x=ai∈L,且ai是第一个与x相等时;−1 x不属于L时。
7)插入:
Insert(L,x,i)。将元素x插入到表L中第i个元素ai之前,且表长+1。
插入前: ( a 0 , a 1 , . . . , a i − 1 , a i , a i + 1 . . . , a n − 1 ) (a_0,a_1,...,a_{i-1},a_i,a_{i+1}...,a_{n-1}) (a0,a1,...,ai−1,ai,ai+1...,an−1) 0≤i≤n,i=n时,x插入表尾
插入后: ( a 0 , a 1 , . . . , a i − 1 , x , a i , a i + 1 . . . , a n − 1 ) (a_0,a_1,...,a_{i-1}, x, a_i,a_{i+1}...,a_{n-1}) (a0,a1,...,ai−1,x,ai,ai+1...,an−1)
8)删除:
Delete(L,i)。删除表L中第i个元素ai,且表长减1, 要求0≤i≤n-1。
删除前: ( a 0 , a 1 , . . . , a i − 1 , a i , a i + 1 . . . , a n − 1 ) (a_0,a_1,...,a_{i-1},a_i,a_{i+1}...,a_{n-1}) (a0,a1,...,ai−1,ai,ai+1...,an−1)
删除后: ( a 0 , a 1 , . . . , a i − 1 , a i + 1 . . . , a n ) (a_0,a_1,...,a_{i-1},a_{i+1}...,a_n) (a0,a1,...,ai−1,ai+1...,an)
代码
test.c
#include <stdio.h>
#include "sqlist.h"
void test_insert();
void test_delete();
void test_merge();
void test_purge();
int main(int argc, char *argv[])
{
//test_insert();
//test_delete();
//test_merge();
test_purge();
return 0;
}
void test_insert()
{
sqlink L;
L = list_create();
if(NULL == L)
return;
list_insert(L, 10, 0);
list_insert(L, 20, 0);
list_insert(L, 30, 0);
list_insert(L, 40, 0);
list_insert(L, 50, 0);
list_insert(L, 60, 0);
list_show(L);
list_insert(L, 100, 0);
list_show(L);
list_free(L);
}
void test_delete()
{
sqlink L;
L = list_create();
if(NULL == L)
return;
list_insert(L, 10, 0);
list_insert(L, 20, 0);
list_insert(L, 30, 0);
list_insert(L, 40, 0);
list_insert(L, 50, 0);
list_insert(L, 60, 0);
list_show(L);
list_delete(L, 6);
list_show(L);
list_free(L);
}
void test_merge()
{
sqlink L1, L2;
L1 = list_create();
if(NULL == L1)
return;
L2 = list_create();
if(NULL == L2)
return;
list_insert(L1, 10, 0);
list_insert(L1, 20, 0);
list_insert(L1, 30, 0);
list_insert(L1, 40, 0);
list_insert(L1, 50, 0);
list_insert(L1, 60, 0);
list_show(L1);
list_insert(L2, 10, 0);
list_insert(L2, 70, 0);
list_insert(L2, 30, 0);
list_insert(L2, 80, 0);
list_insert(L2, 50, 0);
list_insert(L2, 90, 0);
list_show(L2);
list_merge(L1, L2);
list_show(L1);
list_free(L1);
list_free(L2);
}
void test_purge()
{
sqlink L;
L = list_create();
if(NULL == L)
return;
list_insert(L, 10, 0);
list_insert(L, 20, 0);
list_insert(L, 20, 0);
list_insert(L, 40, 0);
list_insert(L, 20, 0);
list_insert(L, 40, 0);
list_show(L);
list_purge(L);
list_show(L);
list_free(L);
}
sqlist.h
#if 0
typedef int data_t;//
#define N 128
struct sqlist_t
{
data_t data[N];
int last;
};
typedef struct sqlist_t sqlist;//sqlist L;struct sqlist_t sqlist L;
typedef struct sqlist_t * sqlink;//struct sqlist_t *p;sqlink p;
#endif
typedef int data_t;
#define N 128
typedef struct
{
data_t data[N];
int last;
}sqlist,* sqlink;
sqlink list_create();
int list_clear(sqlink L);
int list_free(sqlink L);
int list_empty(sqlink L);
int list_length(sqlink L);
int list_lacate(sqlink L, data_t value);
int list_insert(sqlink L, data_t value, int position);
int list_show(sqlink L);
int list_delete(sqlink L, int position);
int list_merge(sqlink L1, sqlink L2);
int list_purge(sqlink L);
sqlist.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlist.h"
sqlink list_create()
{
//malloc
sqlink L;
L = malloc(sizeof(sqlist));
if(NULL == L)
{
printf("malloc failed\n");
return L;
}
//initialize
memset(L, 0, sizeof(sqlist));
L->last = -1;
//return
return L;
}
/* list_clear:clear list
* para:list
* @ret 0-success -1-failed
* */
int list_clear(sqlink L)
{
if(NULL == L)
{
return -1;
}
memset(L, 0, sizeof(sqlist));
L->last = -1;
return 0;
}
int list_free(sqlink L)
{
if(NULL == L)
{
return -1;
}
free(L);
L = NULL;
return 0;
}
/*
* list_empty:Is list empty?
* para L:list
* @ret 1--empty 0--not empty
* */
int list_empty(sqlink L)
{
if(L->last == -1)
{
return 1;
}
else
{
return 0;
}
}
/*
* list_length:Calculate the linear list lenght
* para L:list
* @ret -1--invalid list Otherwise than,it is the actual length
* */
int list_length(sqlink L)
{
if(NULL == L)
{
return -1;
}
else
{
return (L->last+1);
}
}
/*
* list_lacate:Positioning parameter position
* para: list
* @ret -1 not exsit Otherwise than, it is the actual lacate
* */
int list_lacate(sqlink L,data_t value)
{
int i;
for(i = 0; i <= L->last; i++)
{
if(L->data[i] == value)
{
return i;
}
}
return -1;
}
int list_insert(sqlink L,data_t value,int position)
{
int i;
//full
if(L->last == N-1)
{
printf("list is full\n");
return -1;
}
//check para 0<=position<=last+1 [0, last+1]
if(position < 0 || position > L->last+1)
{
printf("position is invalid\n");
return -1;
}
//move
for(i = L->last; i >= position; i--)
{
L->data[i+1] = L->data[i];
}
//updata
L->data[position] = value;
L->last++;
return 0;
}
int list_show(sqlink L)
{
int i;
if(NULL == L)
{
return -1;
}
if(L->last == -1)
{
printf("list is empty\n");
}
for(i = 0; i <= L->last; i++)
{
printf("%d ", L->data[i]);
}
puts("");
return 0;
}
int list_delete(sqlink L, int position)
{
int i;
if(L->last == -1)
{
printf("list is empty\n");
return -1;
}
//position [0, last]
if(position < 0 || position > L->last)
{
printf("delete position is invalid\n");
return -1;
}
//move [position+1, last]
for(i = position + 1; i <= L->last; i++)
{
L->data[i-1] = L->data[i];
}
//updata
L->last--;
return 0;
}
int list_merge(sqlink L1, sqlink L2)
{
int i = 0;
int ret;
while(i <= L2->last)
{
ret = list_lacate(L1, L2->data[i]);
if(ret == -1)
{
if(list_insert(L1, L2->data[i], L1->last+1) == -1)
{
return -1;
}
}
i++;
}
return 0;
}
int list_purge(sqlink L)
{
int i = 1;
int j;
if(L->last == 0)
{
return 0;
}
while(i <= L->last)
{
j = i - 1;
while(j >= 0)
{
if(L->data[i] == L->data[j])
{
list_delete(L, i);
break;
}
else
{
j--;
}
}
if(j < 0)
{
i++;
}
}
return 0;
}