学习 严蔚敏讲数据结构笔记04

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>

 

你可能感兴趣的:(学习 严蔚敏讲数据结构笔记04)