2.1 线性表的类型定义.
2.2 线性表的顺序映象.
2.3 线性表的链式映象.
这里写目录标题
用一组地址连续的存储单元依次存放线性表中的数据元素。
线性表的起始地址,称作线性表的基地址。
以“储位置相邻”表示有序对
<
a
i
,
a
i
+
1
>
<a_{i}, a_{i+1}>
<ai,ai+1>
即:
L
O
C
(
a
i
+
1
)
=
L
O
C
(
a
i
)
+
C
LOC(a_{i+1})=LOC(a_{i})+C
LOC(ai+1)=LOC(ai)+C
C
C
C表示一个数据元素所占存储量,
所有数据元素的存储位置均取决于第一个数据元素的存储位置
L
O
C
(
a
i
)
=
L
O
C
(
a
1
)
+
(
i
−
1
)
∗
C
LOC(a_{i}) =LOC(a_{1}) + (i-1)*C
LOC(ai)=LOC(a1)+(i−1)∗C
基地址
顺序映像的C语言描述
#define LIST_INIT_SIZE 80 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct{
ElemType * elem;// 存储空间基址
int length; // 当前长度
int listsize; // 当前分配的存储容量(以sizeof(ElemtType)为单位)
}SqList, //俗称顺序表
线性表的初始化操作
Status InitList_Sq(SqList &L){
//构造一个空的线性表
L.elem = (ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!L.elem){
exit(OVERFLOW);
}
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return OK;
}//InitList_Sq
线性表操作
LocateElem(L, e, compare())的实现:
int LocateElem_Sq(SqList L, ElemType e, Status (*compare)(ElemType, ElemType)){
i = 1; //i的初值为第1元素的位序
p = L.elem; //p的初值为第1元素的存储位置
while(i <= L.length && !(*compare)(*p++, e)){
++i;
}
if(i <= L.length){
return i;
}else{
return 0; //此线性表中不存在与e有compare关系的元素
}
} //LocateElem_Sq
线性表操作
ListInsert(&L, i, e)的实现:
Status ListInsert_Sq(SqList &L, int pos, ElemType e) {
// 在顺序线性表L中第pos个位置之前插入新的元素e,
// pos的合法值为 1 <= pos <= ListLength_Sq(L)+1
if(pos<1 || pos> L.length+1){
return ERROR; // i值不合法
}
if(L.length >= L.listsize){ //当前存储空间已满,增加分配
newbase = (ElemType *)realloc(L.elem,(L.listsize + LISTINCREMENT) * sizeof(ElemType));
if(!newbase){ //存储分配失败
exit(OVERFLOW);
}
L.elem = newbase;//新基址
L.listsize += LISTINCREMENT; //增加存储容量
}
q = &(L.elem[pos-1]);//q为插入位置
for(p=&(L.elem[L.length-1]); p>=q; --p){
*(p+1) =*p;//插入位置及之后的元素右移
}
*q = e;//插入e
++L.length; //表长增1
return OK;
}//ListInsert_Sq
此算法时间复杂度为:
O
(
L
i
s
t
L
e
n
g
t
h
(
L
)
)
O(ListLength(L))
O(ListLength(L))
考虑平均的情况:
假设在第i个元素之前插入的概率为
p
i
p_{i}
pi ,则在长度为n的线性表中插入一个元素所需移动元素次数的期望值为:
E
i
s
=
∑
i
=
1
n
+
1
p
i
(
n
−
i
+
1
)
E_{is} = \sum_{i=1}^{n+1} p_{i} (n-i+1)
Eis=i=1∑n+1pi(n−i+1)
若假定在线性表中任何一个位置上进行插入的概率都是相等的,则移动元素的期望值为:
E
i
s
=
1
n
+
1
∑
i
=
1
n
+
1
(
n
−
i
+
1
)
=
n
2
E_{is} = \frac {1} {n+1}\sum_{i=1}^{n+1} (n-i+1) = \frac {n}{2}
Eis=n+11i=1∑n+1(n−i+1)=2n
线性表操作ListDelete(&L, i, &e)的实现
Status ListDelete_Sq(SqList &L, int i, ElemType &e) {
// 在顺序线性表L中删除第i个元素,并用e返回其值
// i的合法值为1<=i<=ListDelete_Sq(L)
if((i<1) || (i>L.length)){//i值不合法
return ERROR;
}
p = &(L.elem[i-1]);//p为被删除元素的位置
е = *p;//被删除元素的值赋给e
q = L.elem + L.length-1;//表尾元素的位置
for (++p; p<=q; ++p){
*(p-1) = *p;//被删除元素之后的元素左移
}
--L.length;//表长减1
return OK;
}//ListDelete_Sq
此算法的时间复杂度:
O
(
L
i
s
t
L
e
n
g
t
h
(
L
)
)
O(ListLength(L))
O(ListLength(L))
考虑平均的情况:
假设删除第i个元素的概率为
q
i
q_{i}
qi 则在长度为n的线性表中删除一个元素所需移动元素次数的期望值为:
E
d
l
=
∑
i
=
1
n
q
i
(
n
−
i
)
E_{dl} = \sum_{i=1}^{n} q_{i} (n-i)
Edl=i=1∑nqi(n−i)
若假定在线性表中任何一个位置上进行删除的概率都是相等的,则移动元素的期望值为:
E
d
l
=
1
n
∑
i
=
1
n
(
n
−
i
)
=
n
−
1
2
E_{dl} = \frac {1} {n}\sum_{i=1}^{n} (n-i) = \frac {n-1}{2}
Edl=n1i=1∑n(n−i)=2n−1
// 线性表的动态分配 顺序存储结构
# include <stdio.h>
# include <malloc.h> //包含了malloc函数
# include <stdlib.h> //包含了exit函数
#define LIST_INIT_SIZE 100 // 线性表存储空间的初始分配量
#define LIST_INCREMENT 10 // 线性表存储空间的分配增量
typedef int ElemType; //
typedef int Status; //
#define OK 0
#define ERROR 1
#define OVERFLOW 1
typedef struct SqList{
ElemType * elem; // 元素存储基地址
int length; // 线性表的当前长度
int list_size; // 当前分配的存储容量(以sizeof(ElemType)为单位)
} SqList;
Status Init_List_Sq(SqList &L){
// 构造一个空的线性表L
L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!L.elem){
exit(OVERFLOW);
}
L.length = 0;
L.list_size = LIST_INIT_SIZE;
return OK;
}
Status Append_List_Sq(SqList &L,ElemType val){
if(L.length >= L.list_size){
return ERROR;
}
L.elem[L.length] = val;
L.length++;
return OK;
}
Status Show_List_Sq(SqList &L){
printf("当前线性表有 %d 个元素\n",L.length);
for(int i=0;i<L.length;++i){
printf("%d\t",L.elem[i]);
}
printf("\n");
return OK;
}
Status Insert_List_Sq(SqList &L, int i, ElemType e){
// 在顺序线性表L中第i个位置之前插入新的元素e
// i的合法值为 1 <= i <= ListLength_Sq(L)+1
if(i<1 || i>L.length+1){// i值不合法
return ERROR;
}
if(L.length >= L.list_size){// 当前存储空间已满,增加分配
ElemType * newbase = (ElemType *)realloc(L.elem, (L.list_size+LIST_INCREMENT)*sizeof(ElemType));
if(!newbase){
exit(OVERFLOW); // 存储空间分配失败
}
L.elem = newbase; // 新基址
L.list_size += LIST_INCREMENT; // 增加存储容量
}
ElemType * q = &(L.elem[i-1]); // q为插入位置
for(ElemType * p = &(L.elem[L.length-1]); p>=q; --p){
*(p+1) = *p; // 插入位置及之后的元素右移
}
*q = e; // 插入e
++L.length; // 表长度增加1
return OK;
}
Status Delete_List_Sq(SqList &L, int i, ElemType &e){
// 在顺序线性表L中删除第i个元素,并用e返回其值
// i的合法值为 1 <= i <= ListLength_Sq(L)
if((i<1) || (i>L.length)){
return ERROR;// i值不合法
}
ElemType * p = &(L.elem[i-1]);//
e = *p;
ElemType * q = L.elem + (L.length - 1);
for(++p; p<=q; ++p){
*(p-1) = *p;
}
--L.length;
return OK;
}
// 比较两个元素的大小:相等返回1;不相等返回0
Status compare(ElemType a, ElemType b){
if(a == b){
return 1;
}
return 0;
}
int LocateElem_Sq(SqList L, ElemType e, Status (* compare)(ElemType,ElemType)){
// 在顺序线性表L中查找第1个值与e满足compare()的元素的位序
// 若找到,则返回其在L中的位序,否则返回0
int i = 1;
ElemType * p = L.elem;
while(i <= L.length && !(*compare)(*p, e)){
p++;
i++;
}
if(i <= L.length){
return i;
}
return 0;
}
void Merge_List_Sq(SqList La, SqList Lb,SqList &Lm){
// 已知顺序线性表La和Lb的元素按值非递减排列
// 归并La和Lb得到新的顺序线性表Lm,Lm的元素也按值非递减排列
ElemType * pa = La.elem;
ElemType * pb = Lb.elem;
Lm.list_size = Lm.length = La.length + Lb.length;
ElemType * pm = Lm.elem = (ElemType * )malloc(Lm.list_size * sizeof(ElemType));
if( !Lm.elem ){
exit(OVERFLOW); // 存储空间分配失败
}
ElemType * pa_last = La.elem+(La.length-1);
ElemType * pb_last = Lb.elem+(Lb.length-1);
while(pa <= pa_last && pb <= pb_last){ // 归并
if(*pa <= *pb){
*pm++ = *pa++;
} else {
*pm++ = *pb++;
}
}
while(pa <= pa_last){ // 插入La的剩余元素到Lm
*pm++ = *pa++;
}
while(pb <= pb_last){ // 插入Lb的剩余元素到Lm
*pm++ = *pb++;
}
}
int Func(int x); /*声明一个函数*/
void main(){
SqList L;
printf("%d\n",sizeof(L));
Init_List_Sq(L);
printf("%d\n",sizeof(L));
Append_List_Sq(L,99);
Append_List_Sq(L,77);
Show_List_Sq(L);
Insert_List_Sq(L,1,11);
Show_List_Sq(L);
ElemType e;
Delete_List_Sq(L,1,e);
Show_List_Sq(L);
printf("e = %d\n",e);
int val = 77;
int index = LocateElem_Sq(L,val,compare);
printf("index = %d\n",index);
/*
// C,C++中非0代表真,0代表假
int i =-2;
if(i){
printf("TRUE i=%d", i);
} else {
printf("FALSE i=%d", i);
}
*/
/*
int (*p)(int x); //定义一个 函数指针
p = Func; //将Func函数的首地址赋给指针变量p
(*p)(999); // 使用 函数指针 调用 函数
*/
}
int Func(int x){
printf("您传入的参数 x = %d\n",x);
return 0;
}