1、线性结构的特点
1)存在唯一一个”第一个“数据元素;
2)存在唯一一个“最后一个”数据元素;
3)除第一个外,集合中的每一个数据元素均只有一个前驱;
4)除最后一个外,集合中的每一个数据元素均只有一个后继;
2、线性表的定义
一个线性表是n个元素组成的有限序列,一个数据元素由若干数据项组成,由若干个数据项组成的数据元素又称为记录(数据库中的行)。同一线性表中的元素必定具有相同特性,属于同一数据对象,相邻数据元素之间存在序偶关系。含有大量记录的线性表又称为文件。
3、线性表的顺序存储结构(顺序映像)------顺序表
线性表的顺序表示是指用一组地址连续的存储单元,依次存储线性表的数据元素。
即线性表在硬盘上开辟的是一块连续的存储空间,物理地址是连续的。
第一个数据元素的存储位置称作线性表的起始位置或基地址。
特点:1)相邻数据元素的存储位置相邻
2)每一个数据元素的存储位置都和线性表的起始位置相差一个和数据元素在线性表中的位序成正比的常数。(通俗了讲,由于线性表中数据元素的类型必须统一,所以在进行线性存储的时候,相邻的存储空间内,分给每一个数据元素的存储空间的大小都是相等的,第一个元素存储位置确定后,剩余元素的存储位置就是基地址加上偏移量,偏移量的算法就是位序乘以每个数据元素所占存储空间的大小。
3)顺序表可随机存取。PS:由于逻辑上相邻的数据元素的物理存储位置也是相邻的,因此若是对线性表进行插入和删除操作则必须移动元素。
(-------原谅我到这里联想到了操作系统的索引结构,链式索引结构,定长存取,不定长存取等等一系列页式存储方式-------开学找个机会再总结一下,手头没书--_--)
4)通常用数组来表示线性表,线性表长度可变。
4、线性表的初始化操作:
目的:1)为线性表分配一个预定义大小的数组空间
2)将线性表的当前长度设置为0。
//线性表的动态分配顺序存储结构
#define LIST_INIT_SIZE 100//线性表存储空间的初始分配量
#define LISTINCRECEMENT 10//分配增量
typedef struct{
int *elem;//表示线性表的基地址
int length;//线性表的当前长度
int listsize;//当前分配的存储容量(以数据元素类型为增加单位)
}Sqlist;
//构造一个空的线性链表
int InitList_Sq(SqList &L){
L.elem = (int *)malloc(LIST_INIT_SIZE*sizeof(int));//元素初始分配位置
if (!L.elem)exit(OVERFLOW);//存储空间分配失败
L.length = 0; //空表长度为0
L.listsize = LIST_INIT_SIZE;//线性表的初始大小为预分配大小(即数组个数)
}
5、顺序表的插入
在第I(1<=i<=n)个位置上插入一个元素,则从第i+1到第n个元素的位置都需要后移一个单位长度。
//线性表的插入
int ListInsert_Sq(SqList &L, int i, int e){
//插入的新元素为e数据类型为int
//i的取值范围为1<=i<=ListLength_Sq(L)+1
int *newbase,*q,*p;
if (i<1 || i>L.length + 1)return -1;//插入位置不合法
if (L.length >= L.listsize){//如果超长
newbase = (int *)realloc(L.elem, (L.listsize + LISTINCRECEMENT)*sizeof(int));//物理新基址
if (!newbase)return -1;//没有足够大小的连续物理存储空间 报错
L.elem = newbase;//改变新基址
L.listsize += LISTINCRECEMENT;//线性表大小增加
}
q = &(L.elem[i - 1]);//q为插入位置
for (p = &(L.elem[L.length - 1]); p >= q; --p)//从插入位置往后一直到最后一个元素全部后移一个位置
*(p + 1) = *p;
*q = e;//移好位置之后把元素放上去
++L.length;//总长度顺理成章的+1
return 1;
}
6、线性表的删除
//线性表的删除
int listDelete(SqList &L, int i, int &e){
if (i<1 || i>L.length + 1)return -1;
int *p, *q;
p = &L.elem[i - 1];//要删除的元素位置
e = *p;//用e接住要删除的元素
q = L.elem + L.length - 1;//表尾元素的位置
for (++p; p <= q; ++p)*(p - 1) = *p;//被删除元素后面的所有元素前移一个位置
--L.length;//线性表的总长度-1
}
7、在线性表中查找某个特定元素
操作:让e与顺序表中元素逐个进行比较
//在顺序表中查找并返回第一个与e满足compare的值的位序
int LocateElem_Sq(SqList L, int e,int (*compare)(int,int)){
int i = 1,*p;//i的初值为第一个元素的位序
p = L.elem;//p的初值为第一个元素的存储位置
while (i <= L.length&&!(*compare)(*p++, e))++i;
if (i <= L.length)return i;
else return 0;
}
8、顺序表的合并
//前提是顺序表la和lb都已经按照非减序排列
void mergeList_Sq(SqList la, SqList lb, SqList &lc){
int* pa = la.elem;
int* pb = lb.elem;
lc.length = la.length + lb.length;
lc.listsize = lc.length;
lc.elem = (int *)malloc(lc.listsize*sizeof(int));
int *pc = lc.elem;
if (!pc)exit(OVERFLOW);
int *pa_last = la.elem + la.length - 1;//顺序表la的最后一个元素位置
int *pb_last = lb.elem + lb.length - 1;//顺序表lb的最后一个元素位置
while (pa <= pa_last&&pb <= pb_last){//按照非递减顺序合并到lc
if (*pa <= *pb)*pc++ = *pa++;
else *pc++ = *pb++;
}
while (pa <= pa_last)*pc++ = *pa++;//la比lb长
while (pb <= pb_last)*pc++ = *pb++;//lb比la长
}