分享
 
 
 

数据结构学习笔记(2)partI

王朝other·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

第2章 线形表

所学内容:线性表的类型定义;线性表类型的实现——顺序映象;链式映象;一元多项式的表示。

线性结构:一个数据元素的有序(次序)集。

线性结构的基本特征:集合中必存在唯一的一个“第一元素”;集合中必存在唯一的一个“最后元素”;除最后元素外,均有唯一的后继;除第一元素外,均有唯一的前驱。

一.线性表的类型定义

ADT List{

数据对象:

D = {

a(i) |

a(i)属于ElemSet, i = 1, 2, …..n,

n>= 0 } 称n为线形表的表长,称n=0时的线形表为空表

数据关系:

R1 = {<

a(i-1) ,a(i)

> | a(i-1)

, a(i) 属于

D, i = 2, …… n}

设线形表为(

a(1),a(2)

,。。。。a(i)

,。。。。。。。a(n)

)称i为a在线形表中的次序。

基本操作:

{结构初始化}

InitList(&L)

操作结果:构造一个空的线形表L。

{销毁结构}

DestroyList(&L)

初始条件:线性表L存在。

操作结果:销毁线性表L。

{引用型操作}

ListEmpty(L)

ListLength(L)

PriorElem(L,

cur_e, &pre_e)

NextElem(L, cur_e,

&next_e)

GetElem(L, i,

&e)

LocateElem(L, e,

compare() )

ListTraverse(L,

visit() ) 遍历

{加工型操作}

ClearList(&L)

PutElem(L, i,

&e)

ListInsert(&L,

i, e)

ListDelete(&L,

i, &e)

例1:

假设:有两个集合A和B分别用两个线性表LA和LB表示

现要求新的集合A = A

与B的并集

上述问题演绎为:

要求对线形表做如下操作:

扩大线性表LA,将存在于线性表LB中而不存在于线性表LA中的数据元素插入到线形表LA中去。

具体步骤:

1. 从线形表LB中依次取得每个元素;GetElem(LB, i) -->e

2. 依值在线形表LA中进行查访;LocateElem(LA, e, equal())

3. 若不存在,则插入之。ListInsert(LA, n+1, e)

void union(List

&La, List Lb)

{

La_len = ListLength(La);

Lb_len = ListLength(Lb); //求线形表的长度

For(i=1; i

<=Lb_len; i ++)

{

GetElem(Lb, i, e); //取Lb中第I个元素赋给e

If(! LocateElem(La, e, equal())

ListInsert(La, ++La_len, e);

//La中不存在和e 相同的数据元素,则插入

}

}

例2:

已知一个非纯集合B(数据元素有重复),试构造一个纯集合A(数据元素无重复),使A中只包含B中所有值各不相同的数据元素。

解法1:对集合B不进行排序

void purge(List

&La, List Lb)

{

InitList(La); //设置空的线形表La

La_len = ListLength(La);

Lb_len = ListLength(Lb); //求线形表的长度

For(i=1; i

<=Lb_len; i ++)

{

GetElem(Lb, i, e); //取Lb中第I个元素赋给e

If(! LocateElem(La, e, equal())

ListInsert(La, ++La_len, e);

//La中不存在和e 相同的数据元素,则插入

}

}

LocateElem时间复杂度为n,还有一个外循环,所以该算法的时间复杂度为

解法2:首先对集合B进行排序,然后调用函数purge(…..)

void purge(List

&La, List Lb)

{

InitList(LA);

La_len = ListLength(La);

Lb_len = ListLength(Lb); //求线形表的长度

For(i=1; i

<=Lb_len; i ++)

{

GetElem(Lb, i, e); //取Lb中第I个元素赋给e

If(ListEmpty(LA) || ! equal(en, e) )

{

ListInsert(La,

++La_len, e)//La中不存在和e 相同的数据元素,则插入

en = e; //en表示LA中的最后一个元素

}

}

}

外循环为n,ListEmpty时间复杂度为常量,所以该算法的时间复杂度为常量n

例3:归并两个“其数据元素按值非递减有序排列的”线性表LA和LB,求得线性表LC也具有同样的特性

设La =(

a(1),a(2)

,。。。。。a(i)

,。。。。。。。a(n)

Lb=(

b(1) ,b(2)

,。。。。。b( j )

,。。。。。。。b(m)

Lc =(c(1)

,c(2)

,。。。。。c(i)

,。。。。。。。c(m+n)

1. 分别从LA和LB中取得当前元素ai和aj;

2. 若ai<=aj,则将ai插入到LC中,否则将bj插入到LC中

void MergeList(List La, List Lb,List &Lc)

{

InitList(Lc);

i=j=1;

k=0;

La_len

= ListLength(La);

Lb_len

= ListLength(Lb);

while((i<=La_len)

&& (j<=Lb_len) )

{

//La和Lb均非空

GetElem(La,

i, ai);

GetElem(Lb,

j, bj);

if(ai

<= bj)

{

ListInsert(Lc,

++k, ai);

++i;

}

else

{

ListInsert(Lc,

++k, aj);

++j;

}

}

//当LA或LB有一个遍历完后

while(i

<= La_len)

{

GetElem(La,

i++, ai);

ListInsert(Lc,

++k, ai);

}

while(j

<= Lb_len)

{

GetElem(Lb,

b++, bj);

ListInsert(Lc,

++k, bj);

}

}

二.线性表类型的实现——顺序映象

1.定义:用一组地址连续的存储单元依次存放线性表中的数据元素。第一个数据元素的的地址,就为该线性表的起始地址,或称做线性表的基地址。

2.顺序映象的C语言描述:

#define

LIST_INIT_SIZE 80 //线性表存储空间的初始分配量

#define

LISTINCREMENT 10 //线性表存储空间的分配增量

typedef

struct{

ElemType *elem; //存储空间基址

Int

length; //当前长度

Int

listsize; //当前分配的存储容量,以sizeof(ElemType)为单位

}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;

}

3.线形表的操作:

a. LocateElem的实现

int LocateElem(SqList L, ElemType e,

Status(*compare)(ElemType, ElemType))

{

i = 0; // i 的初值为第1元素的位序

p = L.elem; //p的初值第1元素的存储位置

While(i <= L.length &&

!(*compare)(*p++, e))

++i;

if(i <= L.length)

return i;

else

return 0;

}

该算法的时间复杂度O(ListLength(L)

b. ListInsert(&L, i, e)的实现

插入元素时,线形表的逻辑结构发生了什么变化?

1.(a1,…….a(i-1),a(i),….,a(n))变为(a1,…….a(i-1),e,a(i),….,a(n))

2.长度加1

status ListInsert_Sq(SqList &L,

int pos, ElemType e)

{

if(pos < 1 || pos > L.length()

) //插入位置不合法

return ERROR;

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;

}

时间复杂度O(ListLength(L))

c. ListDelete(&L, i, &e)的实现:

删除元素时,线性表的逻辑结构发生什么变化?

1.(a1,…….a(i-1),a(i),a(i+1)….,a(n))变为(a1,…….a(i-1),a(i+1),….,a(n))

2. 长度减1

status ListDelete_Sq(SqList &L,

int pos, ElemType &e)

{

if(pos < 1 || pos > 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;

}

时间复杂度O(ListLength(L))

(待续)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有