2.2 线性表的顺序映象

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)+(i1)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=1n+1pi(ni+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=1n+1(ni+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=1nqi(ni)
若假定在线性表中任何一个位置上进行删除的概率都是相等的,则移动元素的期望值为:
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=1n(ni)=2n1


// 线性表的动态分配 顺序存储结构
# 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值