1. 线性表综述:
线性表是具有相同特性数据元素的一个有限序列
该序列中所包含元素的个数叫做线性表的长度
当一个线性表有序时,成为有序表,属于逻辑结构
线性表的逻辑特征:
对于至少含有一个元素的线性表来说
除起始元素没有前驱元素外,其他元素都有一个唯一前驱
除终端元素没有后继元素外,其他元素都有一个唯一后继
在线性表中,每个元素最多只有一个前驱和后继元素
线性表存储结构:
线性表有顺序和链式两类存储结构,前者成为顺序表,后者成为链表
顺序表特点:
无需为元素间的逻辑关系儿增加额外的存储空间
可以随机存取表中的任何一个元素,但是要占用连续的空间
而且插入和删除元素时需要移动大量的元素,平均需要移动n/2个元素
链表特点:
不仅存储每个节点的信息,而且也存储节点之间的关系(通过指针)
链表的地址可以是不连续的,不支持随机访问,插入和删除比较快
链表中的第一个节点的存储位置通常被成为头指针
如果链表有头结点,头指针为头结点的地址
如果没有头结点,头指针为开始节点的地址
通常用头指针来标识一个链表
1、顺序表程序:
//线性表存储空间的初始分配量
#define LIST_INIT_SIZE 10
//顺序存储结构的分配增量
#define LIST_INCREMENT 5
typedef int ElemType;
//顺序存储结构体
struct SqList
{
ElemType* elem; //存储空间基址
int length; //数据元素当前长度
int listsize; //当前分配的总容量(元素个数)
};
/*******基础操作********/
//初始化顺序表
void InitList(SqList* L)
{
L->elem = (ElemType*)malloc(sizeof(ElemType)*LIST_INIT_SIZE);
if (L->elem == NULL)
{
printf("空间申请失败!\n");
exit(-1);
}
L->length = 0;
L->listsize = LIST_INIT_SIZE;
}
//销毁顺序表
void DestroyList(SqList* L)
{
free(L->elem);
L->elem = NULL;
L->length = 0;
L->listsize = 0;
}
//清空顺序表
void ClearList(SqList* L)
{
L->length = 0;
}
//判空
int EmptyList(SqList* L)
{
if (L->length == 0)
return 1;
return 0;
}
//顺序表长
int ListLength(SqList* L)
{
return L->length;
}
//得到顺序表第index元素
int GetElem(SqList* L, int index, ElemType* e)
{
//要找的元素不在顺序表范围内
if (index<1 || index>L->length)
return -1;
*e = L->elem[index-1];
return 1;
}
//返回元素的位置
int LocateElem(SqList* L, ElemType* e)
{
for (int i=0; i<L->length; ++i)
{
//元素相等
if (L->elem[i] == *e)
return i;
}
return -1;
}
//返回元素的前驱
int PriorElem(SqList* L, ElemType* e)
{
int index = LocateElem(L, e);
//第一个元素没有前驱
if (index == -1 || index == 0)
return -1;
return index-1;
}
//返回元素的后继
int NextElem(SqList* L, ElemType* e)
{
int index = LocateElem(L, e);
//最后一个元素没有后继
if (index == -1 || index == L->length-1)
return -1;
return index+1;
}
//顺序表插入
int ListInsert(SqList* L, int index, ElemType* e)
{
//判断插入位置是否合法
if (index<1 || index>L->listsize)
return -1;
//判断空间是否满
if (L->length == L->listsize)
{
L->elem = (ElemType*)realloc(L->elem, (L->listsize+LIST_INCREMENT)*sizeof(ElemType));
if (L->elem == NULL)
exit(-1);
L->listsize += LIST_INCREMENT;
}
//开始插入
for (int i=L->length-1; i>=index-1; --i)
{
//循环后移
L->elem[i+1] = L->elem[i];
}
//插入
L->elem[index-1] = *e;
//长度++
L->length++;
return 1;
}
//顺序表删除
int ListDelete(SqList* L, int index)
{
//判断删除位置是否合法
if (index<1 || index>L->length)
return -1;
//开始删除
for (int i=index-1; i<L->length; ++i)
{
L->elem[i] = L->elem[i+1];
}
--L->length;
return 1;
}
//顺序表遍历
void ListTraverse(SqList* L)
{
for (int i=0; i<L->length; ++i)
{
cout << L->elem[i] << ' ';
}
cout << endl;
}
/*******进阶操作********/
//合并两个顺序表
//将所有在顺序表Lb中,但不在La中的元素插入到La中
void Union(SqList* La, SqList* Lb)
{
int lena = ListLength(La);
int lenb = ListLength(Lb);
for (int i=0; i<Lb->length; ++i)
{
//在La中没有出现就插入
if (LocateElem(La, &(Lb->elem[i])) == -1)
ListIn