前言
基础概念
线性表是最简单的一种数据结构,是具有相同数据类型的n(n>=0)个数据元素的有限序列。n为表长,当n=0是为空表。线性表L:
L
=
{
x
1
,
x
2
,
⋅
⋅
⋅
,
x
n
}
L=\{x_1,x_2,···,x_n\}
L={x1,x2,⋅⋅⋅,xn}
L
=
{
x
i
∣
x
i
∈
E
l
e
m
S
e
t
,
i
=
1
,
2
,
3
,
⋅
⋅
⋅
,
n
,
n
≥
0
}
L=\{x_i| x_i \in ElemSet, i=1,2,3,···,n,n\geq0\}
L={xi∣xi∈ElemSet,i=1,2,3,⋅⋅⋅,n,n≥0}
线性结构特点:在数据元素的非空有限集中
- 唯一一个“第一个”数据元素 x 1 x_1 x1,称为“表头元素”
- 除第一个元素外,每个元素有且仅有一个直接前驱
- 除最后一个元素外,每个元素有且仅有一个直接后继
- 唯一一个“最后一个”数据元素 x n x_n xn,称为“表尾元素”
线性的特点
- 表中元素的个数有限
- 表中元素具有逻辑上的顺序性,表中元素有其先后次序。
- 表中元素都是数据元素,一般情况下每个元素都是单个元素。
- 表中元素的数据类型都相同,这意味着每个元素占有相同大小的存储空间。
- 表中元素具有抽象性,即仅讨论元素间的逻辑关系,而不考虑元素内容
注意:线性表是一种逻辑结构,表示元素之间一对一的相邻关系。顺序表和链表是指存储结构,两者属于不同层面的概念,因此不要将其混淆。
稍复杂的线性表中,一个数据元素可以由若干个数据项组成。在这种情况下,常把数据元素称为记录,含有大量记录的线性表称为文件。
基本操作
- InitList(&L):初始化表,构造一个空的线性表L
- Length(L):线性表L存在;求表长,即L中数据元素个数
- DestroyList(&L):线性表L存在;销毁线性表L,释放线性表L占据的内存空间
- ClearLIst(&L):线性表L存在;将L置空
- ListEmpty(L):线性表L存在;判空,若L为空则返回TRUE,否则返回FALSE
- LocateElme(L,e):线性表L存在;按值查找,在表L中具有给定关键字的元素
LocateElme(L,e,compare):线性表L存在;查找L中与e满足关系compare()的数据元素 - GetElem(L,i):线性表L存在;查找表L中第i个元素的值
- ListInsert(&L,i,&e):线性表L存在;插入,在表L的第i个位置前插入e
- LIstDelete(&L,i,&e):线性表L存在;删除,删除表L中第i个元素,返回元素值e
- PrintList(L):线性表L存在;输出表L的所有元素值
- ······
顺序表
线性表的顺序存储又称顺序表,存储机制称为顺序存储结构或顺序映像,利用数组的连续存储空间顺序存放线性表的各元素
顺序表的特点是表中的数据元素的逻辑顺序与物理顺序相同,顺序存储结构的主要特点是节省存储空间,因为分配给数据的存储单元全用存放结点的数据(不考虑部分环境不能使用动态数组的情况),结点之间的逻辑关系没有占用额外的存储空间。采用这种方法时,可实现对结点的随机存取,即每一个数据元素的存储位置和线性表的起始位置相差一个和该数据元素的位序成正比的常数。可以由头结点的位置直接计算出来任一结点的存储地址。但是,顺序存储方法的主要缺点是不便于修改,对结点的插入、删除运算时,可能要移动一系列的结点。
静态数组,数组的大小和空间已经固定,一旦空间占满,再加入新的数据就会产生溢出,进而导致程序崩溃。
动态数组,存储数组的空间在程序执行的过程中动态分配,不需要为线性表一次性划分空间。
- 优点:随机存取表中元素,存储密度高。
- 缺点:插入和删除操作需要移动元素。
//静态 顺序存储 线性表
#include <stdio.h>
#include <stdlib.h>
#define ElemType int
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int length;//顺序表的当前长度
}SqList;
//初始化
int InitList(SqList L){
L.length=0;
return 0;
}
//插入
int ListInsert(SqList *L,int i,ElemType e){
int j;
if(i<1 || i>L->length+1){
printf("插入失败\n");
printf("下标超出范围");
return 0;
}
if(L->length>=MaxSize){
printf("插入失败\n");
printf("储存空间已满");
return 0;
}
for(j=L->length;j>i;j--){
L->data[j]=L->data[j-1];
}
L->data[i-1]=e;
L->length++;
printf("插入成功\n");
return 1;
}
//删除
int ListDelete(SqList *L,int i){
int j;
if(i<1 || i>L->length+1){
printf("下标超出范围");
return 0;
}
for(j=i;j<L->length;j++){
L->data[j-1]=L->data[j];
}
L->length--;
printf("删除成功\n");
return 1;
}
//按值查找
int LocateElem(SqList L,ElemType e){
int i;
for(i=0;i<L.length;i++){
if(L.data[i]==e){
return i+1;
}
}
return 0;
}
//输出打印
void PrintList(SqList L)
{
int i;
printf("线性表L:");
for(i = 0;i < L.length;i++)
printf("%d ",L.data[i]);
printf("\n");
}
int main()
{
SqList L;
int p,i,j,n;
ElemType e;
//初始化
InitList(L);
//赋值
printf("输入数据元素个数:");
scanf("%d",&L.length);
if(L.length>MaxSize){
printf("输入错误");
return 0;
}
printf("输入数据元素:");
for(i=0;i<L.length;i++){
scanf("%d",&L.data[i]);
}
PrintList(L);
//查找
printf("\n输入要查找的值:");
scanf("%d",&e);
p=LocateElem(L,e);
if(!p){
printf("查找失败");
}else{
printf("%d 在第%d个位置上\n",e,p);
}
//插入
printf("\n输入要插入的值和插入的位置:");
scanf("%d %d",&n,&j);
ListInsert(&L,j,n);
PrintList(L);
printf("\n删除第几个元素:");
scanf("%d",&i);
ListDelete(&L,i);
PrintList(L);
return 0;
}
//动态 顺序存储 线性表
#include <stdio.h>
#include <stdlib.h>
#define ElemType int
#define ListInitSize 10
typedef struct{
ElemType * data;//数组指针
int length;//长度
int listsize;//容量
}SqList;
//初始化
int InitList(SqList *L){
L->data = (ElemType *)malloc(ListInitSize*sizeof(ElemType));//申请10空间
if(!L->data)//申请失败
return 0;
L->length = 0;//长度0
L->listsize = ListInitSize;
return 1;//申请成功
}
//增加容量
int AddInitList(SqList *L){
ElemType *newdata;
newdata = (ElemType*)realloc(L->data,(L->listsize+ListInitSize)*sizeof(ElemType));//增加空间
if(!newdata)//申请失败
printf("申请空间失败");
return 0;
L->data = newdata;//调指针
L->listsize+= ListInitSize;//新容量
return 1;
}
//插入
int ListInsert(SqList *L,int i,ElemType e){
int j;
if(i<1 || i>L->length+1){
printf("插入失败\n");
printf("下标超出范围");
return 0;
}
if(L->length>=L->listsize){
AddInitList(&L);
}
for(j=L->length;j>i;j--){
L->data[j]=L->data[j-1];
}
L->data[i-1]=e;
L->length++;
printf("插入成功\n");
return 1;
}
//删除
int ListDelete(SqList *L,int i){
int j;
if(i<1 || i>L->length+1){
printf("下标超出范围");
return 0;
}
for(j=i;j<L->length;j++){
L->data[j-1]=L->data[j];
}
L->length--;
printf("删除成功\n");
return 1;
}
//按值查找
int LocateElem(SqList L,ElemType e){
int i;
for(i=0;i<L.length;i++){
if(L.data[i]==e){
return i+1;
}
}
return 0;
}
//输出打印
void PrintList(SqList L)
{
int i;
printf("线性表L:");
for(i = 0;i < L.length;i++)
printf("%d ",L.data[i]);
printf("\n");
}
int main()
{
SqList L;
int p,i,j,n;
ElemType e;
//初始化
InitList(&L);
//赋值
printf("输入数据元素个数:");
scanf("%d",&L.length);
printf("输入数据元素:");
while(n>L.listsize){
if(AddInitList(&L))
return 0;//防止死循环
}
for(i=0;i<L.length;i++){
scanf("%d",&L.data[i]);
}
PrintList(L);
//查找
printf("\n输入要查找的值:");
scanf("%d",&e);
p=LocateElem(L,e);
if(!p){
printf("查找失败");
}else{
printf("%d 在第%d个位置上\n",e,p);
}
//插入
printf("\n输入要插入的值和插入的位置:");
scanf("%d %d",&n,&j);
ListInsert(&L,j,n);
PrintList(L);
printf("\n删除第几个元素:");
scanf("%d",&i);
ListDelete(&L,i);
PrintList(L);
return 0;
}