基本线性表
应用背景
基本线性表是信息的一种表示形式,是所有数据结构中最常用,最简单的一种数据结构。表中数据元素之间满足一种一对一的线性关系。即每个元素只有惟一的前驱(如果存在)和惟一的后继(如果存在)。
基本线性表的逻辑结构
基本线性表的定义
基本线性表是由 n (n >= 0) 个具有相同性质的数据元素组成的有限序列。记为:
List = (a0, a1, a2..., an)
n 称基本线性表的长度,当 n=0 时,称基本线性表为空表。在基本线性表中,a0 称为表头元素,an 称为表尾元素。a0 是 a1 的直接前驱,a1 是 a0 的直接后继。基本线性表的数据元素类型可以是基本数据类型,也可以是构造类型。当基本线性表的数据类型是构造数据类型时,称数据元素为记录,含有大量记录的基本线性表又称文件。
基本线性表是一种简单而又应用非常广泛的数据结构,基本线性表与数组是有区别的,从概念上来看,基本线性表是一种抽象数据类型,数组是一种具体的数据结构。
基本线性表的运算
基本线性表虽然是一个最简单的数据结构,但其运算相当灵活,使用也比较频繁。根据实际需要其长度可以伸长或缩短,对它的数据元素不仅可以访问,而且可以进行插入,删除,等运算。
对基本线性表的基本运算
(1)创建基本线性表
(2)置空基本线性表
(3)判断基本线性表是否为空
(4)求基本线性表的长度
(5)取数据元素
(6)数据元素的定位
(7)数据元素的插入
(8)数据的删除
(9)求直接前驱
(10)求直接后驱
(11)合并
基本线性表的顺序表示及实现
基本线性表在计算机内的存储结构一般有两种方式:一种是顺序(静态)存储,一种是链式(动态)存储。
基本线性表的顺序存储
1. 顺序基本线性表的存储映像
计算机中存储一个基本线性表可以有不同的方法,最简单的一种方法是将线性表中的元素依次存放在计算机主存储器的连续存储单元中(在外存储器也是类似处理)。
由于基本线性表的每个数据元素所占存储单元的数 length 相同,所以,只要知道基本线性表的第一个元素的物理地址(称为基地址)和每个数据元素占的单元数 length,表中元素 ai 的地址,则可以立即由下面公式
locate(ai) = locate(a0) + i * length
求出式中 locate(a0) 即为表的第一个元素的存储地址,称为基址或基本线性表的首地址,注意,这个公式是元素序号由 0 到 n-1 安排,若元素序号是由 j 开始安排,则上面的公式变为:
locate(ai) = locate(aj) + (i - j) * length
有了这个确定顺序存储结构基本线性表中元素地址的公式,可以很快求出元素的地址,实现线性表中任意元素的快速存取,其算法时间复杂度为常数级 O(1),与基本线性表的长度无关,由此可知,线性表的连续顺序存储结构具有很高的存取效率,它是一种高效的直接存取存储结构。
2. 顺序基本线性表的特点
顺序基本线性表的优点
(1)对基本线性表中的数据元素可以进行随机存取
(2)查找前驱,后继元素非常快捷
(3)空间利用率高
顺序基本线性表的缺点
(1)在基本线性表中插入和删除数据元素的操作效率不高
因为在顺序存储中,所有元素都是连续的,元素之间没有任何空余位置,要插入一个新数据,就要把待插入位置上的原数据移开,这样就需要移动一连串数据元素,同样删除数据时,也要移动大量元素。
(2)建立空表时,不易确定基本线性表存储空间大小
因为基本线性表的最大存储空间不好估计。
3. 顺序基本线性表的定义
在高级语言中,一维数组是采用有顺序存储结构的,因此可以借用一维数组这样的数据类型来描述线性表的顺序存储结构。
elemtype arrayname[array_len]
这里的 elemtype 是抽象的数据类型,可以是整型,实型,等基本数据类型,也可以是结构体指针类型。
顺序基本线性表也可用结构体的形式定义
typedef int datatype;
#define maxsize 100
typedef struct
{
dataype data[maxsize];
int last;
}sqlist;
基本线性表的顺序存储的运算
基本线性表的类型定义如下:
#define maxsize 100
typedef int elemtype;
typedef struct
{
elemtype num[maxsize];
int length;
}List;
1. 线性表的初始化
初始化基本线性表就是将它的长度设置为0。
void Initlist(List L)
{
L.length = 0;
}
2. 置空基本线性表
将基本线性表中的所有元素删除
void clearlist(List L)
{
L.length = 0;
}
3. 判断基本线性表是否为空
如果为空,返回真(1)否则返回假 (0)
int emptylist(List L)
{
if(L.length == 0)
return 1;
else
return 0;
}
4. 求基本线性表的长度
就是求基本线性表中数据元素的个数,数据元素的个数通过L.length 统计,只要返回 L.length的值。
int lengthlist(List L)
{
return (L.length);
}
5. 取数据元素
从基本线性表的第 i 个位置取出其数据元素。如果 i 是有效位置,即 i 在基本线性表的表示范围内,返回下标为 i - 1 的元素即 L.num[i-1].
elemtype getnum(List L, int i)
{
if((i<0) || (i>L.kength - 1))
printf("position not exsit");
else
return (L.num[i-1]);
}
6. 数据元素的定位
找到与给定值相等的数据的元素,如果找到 则返回其序号(下标加1),否则定位不成功
int locatenum(List L, elemtype x)
{
int i, flag = 1;
for(i=0;i<=L.length;i++)
if(L.num[i] == x)
{
flag =0;
return (i+1);
break;
}
if(flag)
return -1;
}
7. 数据元素的插入
int insertnum(List L, elemtype x, int p)
{
int j;
if(L.length == maxsize)
printf("List overflow");
else if ((p<0) || (p>L.length))
printf("position not exist");
else if(L.length[p] == x)
{
return -1;
break;
}
else
for(j=L.length;j>=p;j++)
L.num[j+1] = L.num[j];
L.num[p] = x;
L.length ++;
return 1;
}
8. 数据元素删除
int deletenum(List L, int p)
{
int j;
if(L.length == 0)
printf("List underflow");
else if((p<0) || (p>L.length))
{
printf("position not existe\n");
return -1;
}
else
for(j=p+1; j<=L.length; j++)
L.num[j - 1] = L.num[j];
L.length --;
return 1;
}
9 求直接前驱
int priornum(List L, elemtype x)
{
int i;
i = locatenum(L, x) - 1;
if(i >= 1)
return (L.num[i - 1]);
else
printf("priornum not exist");
}
10. 求直接后继
int nextnum(List L, elemtype x)
{
int i;
i = locatenum(L, x) + 1;
if((i>0) && (i<L.length))
return (L.num[i+1]);
else
printf("nextnum not exist");
}
基本线性表的单链表操作
类型定义
#define NULL 0
#define LEN sizeof(struct Lnode)
typedef int elemtype;
struct Lnode
{
elemtype data;
struct Lnode *next;
};
struct Lnode *head, *p;
1. 单链表的初始化
struct Lnode *initlist(struct Lnode *head)
{
head = NULL;
}
2. 置空链表
将一个已存在的单链表的元素全部删除,可以有两种办法,实现对单链表的置空,一种办法是令链表头指针为空,这种办法最简单,但是没有释放被删除的节点的存储空间,浪费资源,另一种办法是对单链表的所有节点从表头到表尾进行删除,并释放被删除节点的存储空间,下面给出第二种办法的算法。
struct Lnode *clearlist(struct Lnode *head)
{
struct Lnode *p;
while(head != NULL)
{
p = head;
head = head -> next;
free(p);
}
}
3. 判断单链表是否为空
int emptylist(struct Lnode *head)
{
return (head == NULL);
}
4. 求单链表的长度
int lengthlist(struct Lnode *head)
{
struct Lnode *p;
int j = 0;
p = head;
while(p != NULL)
{
p = p -> next;
j ++;
}
return j;
}
5. 取单链表中的第 i 个数据元素
elemtype getlist(struct Lnode *head, int i)
{
int j = 0;
struct Lnode *p;
p = head;
while((p != NULL) && (j<i))
{
p = p -> next;
j ++;
}
if(p != NULL)
return p->data;
else
return 0;
}
6. 在单链表中查找数据元素 key
int search(struct Lnode *head, int key)
{
struct Lnode *p;
int z = 0;
if(head == NULL)
printf("this is empty list");
else
p = head;
while(p->next != NULL && p->data != key)
p = p -> next;
if(p->data == key)
z = key;
else
z = 0;
retrun z;
}
7. 在单链表里删除第 i 个节点
struct Lnode *delete(struct Lnode *h, int i)
{
int j=1;
struct Lnode *p, *q;
p = h;
while((p != NULL) && (j < i))
{
q = p;
p = p -> next;
j ++;
}
if((p != NULL) && (p->next != NULL))
{
q->next = p->next;
free(p);
}
}
8. 在单链表中给定位置前插入关键字