学习书籍《大话数据结构》,自学完后,总结一下,以后也好复习 ,欢迎互相交流。
线性表的基本操作功能如下:
InitList(*L): 初始化操作,建立一个空的线性表L
ListEmpty(L): 若线性表为空,返回true,否则返回false
ClearList(*L): 将线性表清空
GetElem(L,i,*e) : 将线性表L中的第i个位置元素返回给e
LocateElem(L,e) : 在线性表L中查找与给定值e相等的元素,如果查找成功,返回该元素在表中序号表示成功;否则,返回0表示失败
ListInsert(*L,i,e): 在线性表L中的第i个位置插入新元素e
ListDelete(*L,i,*e): 删除线性表L中第i个位置元素,并用e返回其值
ListLength(L): 返回线性表L的元素个数
对于不同的应用,线性表的基本操作不同,对于现实中更复杂的操作,完全可以用这些基本操作完成。
例如:要实现两个线性表集合的并,将结果存入集合C中。先将集合A插入集合C中,再循环B集合中的每个元素,判断集合A中是否存在,不存在,则插入C。具体实现本代码的void unionL(SqList *Lc, SqList Lb,SqList La);
要实现两个线性表集合的交,将结果存入集合C中。分析略(和交集类似,就不写了),具体实现本代码void insertction(SqList La, SqList Lb, SqList *Lc);
代码如下(编译软件vs2013):
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 30 /*存储空间初始分配量*/
typedef int Status;/*status是函数的类型,其值是函数结果状态代码,如OK等*/
typedef int ElemType; /*ElemType类型根据实际情况而定,这里假设为int*/
//输出元素c
Status visit(ElemType c)
{
printf("%d ", c);
return OK;
}
//线性表的顺序存储结构
typedef struct
{
ElemType data[MAXSIZE];//数组存储数据元素,最大值为MAXSIZE
int length; //线性表当前长度
}SqList;
//初始化顺序线性表
Status InitList(SqList *L)
{
L->length = 0;
return OK;
}
/*初始条件:顺序线性表L存在。操作结果:若L为空表,则返回FALSE,否则返回TRUE*/
Status ListEmpty(SqList L)
{
if (L.length == 0)
return FALSE;
else
return TRUE;
}
//初始条件:顺序线性表L已存在。操作结果:将L重置为空表
Status ClearList(SqList *L)
{
L->length = 0;
return OK;
}
//初始条件:顺序线性表L已存在。操作结果:返回线性表L元素个数
int ListLength(SqList L)
{
return L.length;
}
/*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)
操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始*/
Status GetElem(SqList L, int i, ElemType *e)
{
if (L.length == 0 || i<1 || i>L.length)
return ERROR;
*e = L.data[i - 1];
return OK;
}
/*初始条件:顺序线性表L已存在
操作结果:返回L中第1个与e满足关系的数据元素的位序
若这样的数据元素不存在,则返回值为0*/
int LocateElem(SqList L, ElemType e)
{
int i;
if (L.length) //顺序线性表L存在且不为空
{
for (i = 0; i < L.length;i++)
if (L.data[i] == e)
return i+1;
}
return 0;
}
/*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)
操作结果:在L中第i个位置之前插入新的数据元素e,L中的长度加1*/
Status ListInsert(SqList *L, int i, ElemType e)
{
int k;
if (L->length == MAXSIZE || i < 1 || i>L->length + 1) //L满或i小于1或大于最后一个位置+1
return ERROR;
else
{
if (i <= L->length)
{
for (k = L->length; k >= i; k--)
L->data[k] = L->data[k - 1];
}
L->data[i - 1] = e;
L->length++;
return OK;
}
}
/*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)
操作结果:删除L的第i个元素,并用e返回其值,L的长度减1*/
Status ListDelete(SqList *L, int i, ElemType *e)
{
int k;
if (L->length == MAXSIZE || i < 1 || i>L->length) //L满或i小于1或大于最后一个位置
return ERROR;
*e = L->data[i - 1]; //用e保存要删除的元素
if (i<L->length)
for (k = i - 1; k < L->length-1; k++)
L->data[k] = L->data[k + 1];
L->length--;
return OK;
}
/*初始条件:顺序线性表L已存在
操作结果:依次对L中的每个元素输出*/
Status ListTraverse(SqList L)
{
int i;
for (i = 0; i < L.length; i++)
visit(L.data[i]);
printf("\n");
return OK;
}
//实现两个线性表集合的并集操作
//将所有的线性表中元素不重复的存入Lc中
void unionL(SqList *Lc, SqList Lb,SqList La)
{
int La_len, Lb_len,Lc_len, i,j;
ElemType e; //声明La与Lb相同的元素e
La_len = ListLength(La);
Lb_len = ListLength(Lb);
ClearList(Lc);
Lc_len = ListLength(*Lc);
for (j = 1; j <= La_len; j++)
{
GetElem(La, j, &e); //取La中第i个元素赋给e
ListInsert(Lc, ++Lc_len, e); //插入
}
for (i = 1; i <= Lb_len; i++)
{
GetElem(Lb, i, &e); //取Lb中第i个元素赋给e
if (!LocateElem(*Lc, e)) //La中不存在和e相同数据元素
ListInsert(Lc, ++Lc_len, e); //插入
}
}
//实现两个集合的交集操作
//将所有的在线性表Lb中且在La中的数据元素插入到Lc中
void insertction(SqList La, SqList Lb, SqList *Lc)
{
int La_len, Lb_len, Lc_len, i;
ElemType e;
La_len = ListLength(La);
Lb_len = ListLength(Lb);
ClearList(Lc);
Lc_len = ListLength(*Lc);
for (i = 1; i <= Lb_len; i++)
{
GetElem(Lb, i, &e);
if (LocateElem(La,e)) //La中存在和e相同数据元素
ListInsert(Lc, ++Lc_len, e); //插入
}
}
int main()
{
SqList L;
ElemType e;
Status i;
int j, k;
i = InitList(&L);
printf("初始化L后:L.length=%d\n", L.length);
for (j = 0; j < 8; j++)
ListInsert(&L, 1, j);
printf("L表头依次插入0--7:");
ListTraverse(L);
printf("L是否为空:(1否0是)%d\n", ListEmpty(L));
ClearList(&L);
printf("清空线性表L\n");
printf("L是否为空:(1否0是)%d\n", ListEmpty(L));
for (int j = 1; j <=10; j++)
{
ListInsert(&L, j, j-1);
}
printf("在L表中1--10位置输入0--9数字:");
ListTraverse(L);
GetElem(L, 3, &e);
printf("输出L中第3个元素:%d\n",e );
k = LocateElem(L, 3);
if (k)
printf("找出L中第一个3所在的位置:%d\n",k);
else
{
printf("L中无此元素\n");
}
k = ListDelete(&L, 4, &e);
if (k)
printf("删除L中第4个元素值为: %d\n", e);
else
printf("删除失败\n");
printf("输出L中所有的元素:");
ListTraverse(L);;
SqList Lb;
SqList Lc;
InitList(&Lc);
InitList(&Lb);
for (j = 0; j < 7; j++)
{
ListInsert(&Lb, j, j + 5);
}
printf("输出Lb中所有的元素:");
ListTraverse(Lb);
unionL(&Lc,L, Lb);
printf("输出L和Lb标的并集:");
ListTraverse(Lc);
insertction(L, Lb, &Lc);
printf("输出L和Lb标的交集:");
ListTraverse(Lc);
system("pause");
return 0;
}
结果截图:
![](https://img-blog.csdn.net/201810032213098?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NhaV9uaWFvY2Fpbmlhbw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
插入和删除的平均时间复杂度:O(n)
线性表顺序存储结构的优缺点:
优点: 1.无须为表示表中元素之间的逻辑关系而增加额外的存储空间
2.可以快速地存取表中任一位置的元素
缺点: 1.插入和删除操作需要移动大量元素
2.当线性表长度变化较大时,难以确定存储空间的容量
3.造成存储空间的“碎片”