2.2线性表类型的实现 –顺序映象
用一组地址连续的存储单元依次存放线性表中的数据元素。
线性表的起始地址,称作线性表的基地址。
以“存储位置相邻”表示有序对<ai-1,ai>
即:LOC(ai) = LOC(ai-1)+C
一个数据元素所占存储量
所有数据元素的存储位置均取决于第一个数据元素的存储位置
LOC(ai)=LOC(a1)+(i-1)*C
基地址
顺序映像的C语言描述
03_005 |
#define LIST_INIT_SIZE 80 //线性表存储空间初始分配量 #define LIST_INCREMENT 10 //线性表存储空间的分配增量 typedef struct { ElemType * elem; //存储空间基地址 int length; //当前长度 int listsize; //当前分配存储容量 (以sizeof(ElemType)为单位) }SqList; //俗称顺序表 |
线性表的初始化
04_001 |
Status IintList_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 0K; } //InitList_Sq |
线性表操作
LocateElem(L,e,compare()) 的实现:
问:插入元素时,线性表的逻辑结构发生什么变化?
(a1,…,ai-1,ai,…,an)改变为(a1,…,ai-1,e,ai,…,an)
04_002 |
Status ListInsert_Sq(SqList & L, int pos, ElemType e) { if(pos < 1 || pos > L.length + 1) return ERROR; //插入位置不合法 if(L.length == L.listsize) //当前存储空间已满,增加分配 { newbase = (ElemType *) malloc(LIST_INCREMENT * sizeof(ElemType)); if(! newbase) exit(OVERFLOW); //存储分配失败 L.elem = newbase }
L.listsize = LIST_INCREMENT
q = &(L.elem[pos-1]); //q指示插入位置 for(p = &(L.elem[L.length-1]); p >= q; --p) *(p+1) = *p; //插入位置及之后的元素右移 ++L.length; //表长增1 return OK; } //ListInsert Sq |
此算法的时间复杂度是为:O(ListLength(L))
考虑平均的情况:
假设在第i个元素之前插入的概率为pi,则在长度为n的线性表中插入一个元素所需移动元素次数的期望值为:
若假定在线性表中任何一个位置上进行插入的概率都是相等的,则移动元素的期望值为:
线性表操作
ListDelete(&L,i,&e)的实现:
问:删除元素时,线性表的逻辑结构发生什么样的变化?
(a1,…,ai-1,ai,…,an)改变为(a1,…,ai-1,ai+1,…,an)
04_003 |
Status ListDelete Sq(SqList & L, int pos, ElemType &e) { if((pos < 1) || (pose > L.length)) return ERROR; //删除位置不合法 p = &(L.elem[pos-1]); //p为被删除元素的位置 e = *p; //被删除元素的值赋给e q = L.elem + L.length - 1; //表尾元素的位置 for( ++p; p <= q; ++p) *(p-1) = *p; //被删除元素之后的元素左移 -- L.length; //表长减1 return OK; } //ListDelete_Sq |
此算法的时间复杂度为:O(ListLength(L))
考虑平均的情况:
假设删除第i个元素的概率为qi,则在长度为n的线性表中删除一个元素所需移动元素次数的期望值为:
若假定在线性表中任何一个位置上进行行删除的概率都是相等的,则移动元素的期望值为:
2.2线性表类型的实现 –链式映象
一、单链表
用一组地址任意的存储单元存放线性表中的数据元素
以元素(数据元素的映象)+指针(指示后继元素存储位置的)=结点(表示数据元素)
以“结点的序列”表示线性表—称作链表
以线性表中第一个数据元素a1的存储地址作为线性表的地址,称作线性表的头指针
数据域 | 指针域 |
二、结点和单链表的C语言描述
04_004 |
Typedef struct LNode { ElemType data; //数据域 struct Lnode * next; //指针域 } LNode, *LinkList; |
三、单链表的实现
线性表的操作GetElem(L,i,&e)
在链表中的实现:
基本操作为:使指针p始终指向线性表中第j个元素
04_005 |
Status GetElem_L(LinkList L, int pos, ElemType &e) { p = L->next; j = 1; //初始化,p指向第一个结点,j为计数器 while(p && j<pos) { p = p->next; ++ j; } //指针指向后查找,直到p指向第pos个元素域p为空 if(!p || j>pos) return ERROR; //第pos个元素不存在 e = p->data; //取第pos个元素 return OK; } //GetElem_L |
算法的时间复杂度为:O(ListLength(L))
线性表的操作ListInsert(&L,i,e)
在链表中的实现:
基本操作为:找到线性表中第i-1个结点,修改其指向后继的指针
有序对<ai-1,ai>改变为<ai-1,e>和<e,ai>