1.线性表、
线性表是一个线性结构,它是一个含有n≥0个结点的有限序列,对于其中的结点,有且仅有一个开始结点没有前驱但有一个后继结点,有且仅有一个终端结点没有后继但有一个前驱结点,其它的结点都有且仅有一个前驱和一个后继结点。一般地,一个线性表可以表示成一个线性序列:k1,k2,…,kn,其中k1是开始结点,kn是终端结点。
例如:26个英文字母组成的字母表
(A, B, C,...,Z )
2.顺序表
2.1 顺序表的概念及描述
线性表采用顺序存储的方式存储就称之为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。
如顺序表的每个结点占用len个内存单元,用location(Ki)表示顺序表中第i个结点Ki所占内存空间的第1个单元的地址。则有如下的关系:
location (ki+1) = location (ki) +len
location (ki) = location(k1) + (i-1)len
顺序表的储存结构如下图所示:
2.2 顺序表的实现
C语言中数组的下标是从0开始的,即数组中下标为0的元素对应的是顺序表中的第1个结点,数组中下标为i的元素对应的是顺序表中的第i+1个结点。这样,一个长度为n的顺序表可以表示为 {k0, k1, k2, …, kn-1}
2.2.1 顺序表的C语言描述
/*************************************/
/*顺序表的头文件,文件名:sequlist.h */
/*************************************/
# define MAXSIZE 100
typedef int datatype;
typedef struct {
datatype a[MAXSIZE];
int size;
}sequence_list;
2.2.2 置空表--顺序表的初始化
/***************************************************/
/* 函数功能:顺序表的初始化--置空表 */
/* 函数参数:指向sequenbce_list型变量的指针变量slt */
/* 函数返回值:空 */
/* 文件名:sequlist.c,函数名:init() */
/**************************************************/
void init(sequence_list* slt)
{
slt->size = 0;
}
2.2.3 在顺序表后部进行插入操作
/*************************************************/
/* 函数功能:在顺序表后部进行插入操作 */
/* 函数参数:指向sequence_list型变量的指针变量slt*/
/* datatype类型的变量x */
/* 函数返回值:空 */
/* 文件名:sequlist.c,函数名:append() */
/**************************************************/
void append(sequence_list *slt, datatype x) {
if (slt->size == MAXSIZE) {
print("顺序表是满的!"); exit(1);
}
slt->a[slt->size] = x;
slt->size = slt->size + 1;
}
2.2.4 打印顺序表的各节点值
/**************************************************/
/* 函数功能:打印顺序表的各个节点值 */
/* 函数参数:sequence_list型变量slt */
/* 函数返回值:空 */
/* 文件名:sequlist.c, 函数名:display() */
/**************************************************/
void display(sequence_list slt)
{
int i;
if (!slt.size) {
printf("\n顺序表是空的!");
}
else {
for (i = 0; i < slt.size; i++) {
printf("%5d", slt.a[i]);
}
}
}
2.2.5 判断顺序表是否为空
/***************************************************/
/* 函数功能:查找顺序表中值为x的节点位置 */
/* 函数参数:sequence_list型变量slt,datatype型变量x*/
/* 函数返回值:int类型。1表示空,0表示非空 */
/* 文件名: sequlist.c, 函数名:empty() */
/***************************************************/
int find(sequence_list slt, datatype x) {
int i = 0;
while (i < slt.size && slt.a[i] != x) { i++; }
return (i < slt.size ? i : -1);
}
2.2.6 查找顺序表中值为x的节点位置
/**************************************************/
/* 函数功能:获得顺序表中第i个节点的值 */
/* 函数参数:sequence_list型变量slt,int型变量i */
/* 函数返回值:int类型。1表示空,0表示非空 */
/* 文件名: sequlist.c, 函数名:get() */
/**************************************************/
datatype get(sequence_list slt, int i)
{
if (i<0 || i>slt.size)
{
printf("\n指定位置的结点不存在!"); exit(1);
}
else {
return slt.a[i];
}
}
2.2.7 顺序表的插入操作
2.2.7.1 顺序表插入操作的描述:
顺序表的插入运算是将一个值为x的结点插入到顺序表的第i个位置0≤i≤n,即将x插入到ki-1和ki之间,如果i=n,则表示插入到表的最后,一般地可表示为:
插入前:{k0, k1, …, ki-1, ki, …, kn-1}
插入后:{k0, k1, …, ki-1,x, ki, …, kn-1}
插入过程的图示如下图:
/**************************************************/
/* 函数功能:在顺序表的position位置插入值为x的节点*/
/* 函数参数:指向sequence_list型变量的指针变量slt */
/* datatype类型的变量x,int 类型变量position */
/* 函数返回值:空 */
/* 文件名:sequlist.c,函数名:insert() */
/**************************************************/
void insert(sequence_list *slt, datatype x, int position)
{
int i;
if (slt->size == MAXSIZE)
{
printf("\n顺序表是满的,没法插入!");exit(1);
}
if (position<0 || pisition>slt->MAXSIZE)
{
printf("\n指定的扎入位置不存在!");exit(1);
}
for (i = slt->size; i > position; i--)
{
slt->a[i] = slt->a[i - 1];
slt->a[position] = x;
slt->size++
}
}
2.2.7.2 操作总结
顺序表插入操作中,所花费的时间主要是元素后移操作,对于在第i个位置上插入一个新的元素,需要移动(n-i)个元素,设在第i个位置上插入一个元素的概率为pi,且在任意一个位置上插入元素的概率相等,即p0=p1=p2=…=pn=1/(n+1),则在一个长度为n的顺序表中插入一个元素所需的平均移动次数为:
即在长度为n的顺序表中插入一个元素平均需要移动表中的一半元素。该算法的时间复杂度为(n)。
2.2.8 顺序表的删除操作
2.2.8.1 顺序表删除操作的描述
顺序表的删除操作是指删除顺序表中的第i个结点,0≤i≤n-1,一般地可表示为:
删除前:{k0, k1, …, ki-1, ki, ki+1, ,…, kn-1}
删除后:{k0, k1, …, ki-1, ki+1, …, kn-1}
删除过程的图示见下图 :
/*************************************************/
/* 函数功能:删除顺序表中position位置的结点 */
/* 函数参数:指向sequence_list型变量的指针变量slt*/
/* int型变量position */
/* 函数返回值:空 */
/* 文件名:sequlist.c,函数名:dele` () */
/*************************************************/
void dele(sequence_list *slt, int position)
{
int i;
if (slt->size == 0)
{
printf("\n顺序表是空的!"); exit(1);
}
if (position < 0 || position >= slt->size)
{
printf("\n指定删除的位置不存在"); exit(1);
}
for (i = position; i < slt->size - 1; i++) slt->a[i] = slt->a[i + 1];
slt->size--;
}
2.2.8.2 顺序表删除操作总结
要删除顺序表中的第i个结点,则需要称动(n-i-1)个元素,设删除表中第i个结点的概率为qi,且在表中每一个位置删除的概率相等,即: q0=q1=…=qn-1=1/n
则在一个长度为n的顺序表中删除一个结点的平均移动次数为:
这表明,在一个长为n的顺序表中删除一个元素平均需要移动表中大约一半的元素。该算法的时间复杂度为O(n)。