35
回回 回回回 :( 1/2 为为为为为为为为为 为为为为为为为 回回回回回回回回回回回回回回回回 回回回回回回 回回回回回回回回回回回回回回回回 回回回回回回回回回回回回回回 “回回”回回回回回回回回回回回回回 回回回回回回回回 为为为为为为为 回回回回回回回回回回回回回回回回 回回回 为为为为为为为为为 回回回回回回回回???

回顾:绪论( 1/2 )

  • Upload
    chelsey

  • View
    112

  • Download
    0

Embed Size (px)

DESCRIPTION

回顾:绪论( 1/2 ). 为什么要学数据结构? 什么是数据结构? 研究计算机操作对象及其关系与操作 相互之间存在一种或多种特定关系的数据元素的集合 从操作对象抽象出来的数学模型, “ 关系 ” 描述数据元素之间的逻辑关系,也称之为逻辑结构 什么是数据类型? 值的集合以及定义在这个值集合上的一组操作 什么是抽象数据类型? 与数据类型的差异???. 回顾:绪论( 2/2 ). 算法?算法性能的度量? 时间 空间. 空间复杂度度量. 存储空间的固定部分 程序指令代码的空间,常数、简单变量、定长成分 ( 如数组元素、结构成分、对象的数据成员等 ) 变量所占空间 - PowerPoint PPT Presentation

Citation preview

Page 1: 回顾:绪论( 1/2 )

回顾:绪论( 1/2 ) 为什么要学数据结构? 什么是数据结构?

研究计算机操作对象及其关系与操作 相互之间存在一种或多种特定关系的数据元素的集合 从操作对象抽象出来的数学模型,“关系”描述数据元素之

间的逻辑关系,也称之为逻辑结构 什么是数据类型?

值的集合以及定义在这个值集合上的一组操作 什么是抽象数据类型?

与数据类型的差异???

Page 2: 回顾:绪论( 1/2 )

回顾:绪论( 2/2 ) 算法?算法性能的度量?

时间 空间

Page 3: 回顾:绪论( 1/2 )

空间复杂度度量 存储空间的固定部分存储空间的固定部分

程序指令代码的空间,常数、简单变量、定长成分 ( 如数组元素、结构成分、对象的数据成员等 ) 变量所占空间

可变部分可变部分尺寸与实例特性有关的成分变量所占空间、引用变量所占空间、递归栈所用空间、通过 new 和 delete 命令动态使用空间

空间复杂度 原地工作(额外空间相对输入数据量来说是常数)

O ( 1 )

如果我不用任何附加的空间,实现两个数的交换,怎么做?

Page 4: 回顾:绪论( 1/2 )

算法时间复杂度分析练习( 1/3 ) 2100, (3/2)n , (2/3)n , nn ,n0.5 , n! , 2n , lgn ,nlgn, n

(3/2) 常见的时间复杂度按数量级递增排列 , 依次为 : 常数阶 0(1) 、

对数阶 0(log2n) 、线性阶 0(n) 、线性对数阶 0(nlog2n) 、平方阶 0(n2) 、立方阶 0(n3) 、 k 次方阶 0(nk) 、指数阶 0(2n) 。

先将题中的函数分成如下几类: 常数阶: 2100

对数阶: lgn K 次方阶: n0.5 、 n(3/2)

指数阶 ( 按指数由小到大排 ) : nlgn 、 (3/2)n 、 2n 、 n! 、 nn

注意: (2/3)^n 由于底数小于 1 ,所以是一个递减函数,其数量级应小于常数阶。 根据以上分析按增长率由小至大的顺序可排列如下:(2/3)n < 2100 < lgn < n0.5 < nlgn < n(3/2) < (3/2)n < 2n < n! < nn

Page 5: 回顾:绪论( 1/2 )

算法时间复杂度分析练习( 2/3 ) 给一个实数序列,求子序列的最大和 int MaxSubeqSum ( const int A[],int N){ int thisusm,maxsum,i,j,k;

for (maxsum=0,i=0;i<N;i++)for(j=i;j<N;j++){

thissum=0;for(k=i;k<=j;k++)

thissum+=A[k];if(thissum>maxsum)

maxsum=thissum;}

return maxsum;}

Page 6: 回顾:绪论( 1/2 )

算法时间复杂度分析练习( 3/3 ) 求菲波拉契数: f0=1 , f1=1 , fn=fn-1+fn-2

Long int Fib(int n) { if (N<=1) return 1; else return Fib(n-1)+Fib(n-2); }

时间复杂度?能有更好的算法吗?(时间复杂度低)

Page 7: 回顾:绪论( 1/2 )

第二章 线性表第二章 线性表 线性表的类型定义 线性表的顺序表示和实现 线性表的链式表示 线性表的应用

Page 8: 回顾:绪论( 1/2 )

线性结构线性结构

特点 : 数据的非空有限集合中, 存在唯一的一个被称作“第一个”的数据元素; 存在唯一的一个被称做“最后一个”的数据元素; 除第一个元素外,其他每一个元素有一个且仅有一个

直接前驱。 除最后一个元素外,其他每一个元素有一个且仅有一

个直接后继。

za b c y

线性结构示例:英文字母表

Page 9: 回顾:绪论( 1/2 )

线性表的类型定义线性表的类型定义定义 : 线性表 (Linear list )是 n( 0 )个数据元素的有限序列,记作( a1, …ai-1, ai , ai+1 , …,

an),其中 ai 是表中数据元素, n 是表长度。 i 称为 ai在线性表中的位序 ;n=0 是为空表。 特点: 同一线性表中的元素具有相同特性 复杂的数据元素可由若干个数据项组成 相邻数据元素之间存在序偶关系

Page 10: 回顾:绪论( 1/2 )

例子 (1,2,3,4,5,6,7,8,9,10,11) (2,5,7,4,8,4,3,6,7,44444,3) (‘ab’,’cd’,’af’,’adsd’) 字符串 以下是错误的例子 (a,b,c,d) ,其中 a=3,b=5,c=‘a’,d=(1,2) 自然数

Page 11: 回顾:绪论( 1/2 )

线性表的 ADT 定义ADT List{ 数据对象: D={ai| ai ElemSet,i=1,2,…,n,n 0} 数据关系: R1={< ai-1, ai >| ai-1, ai D,i=2,…n} 基本操作: InitList(&L) DestroyList(&L) ClearList(&L) ListEmpty(L) ListLength(L) GetElem(L,i,&e)

Page 12: 回顾:绪论( 1/2 )

线性表的 ADT 定义 LocateElem(L,e,compare( )) PriorElem(L,cur_e,&pre_e) NextElem(L,cur_e,&next_e) ListInsert(&L,i,e) ListDelete(&L,i,&e) ListTraverse(L,visit( )) } ADT List 在此 ADT 基础上还可定义更复杂的一些操作

Page 13: 回顾:绪论( 1/2 )

两个更复杂的操作两个更复杂的操作 (1)(1) 例 2-1: 集合的并 (union) 操作 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); if (! LocateElem(La,e,equal)) ListInsert(La,++La_len,e); } } //union 算法 2.1

Page 14: 回顾:绪论( 1/2 )

两个更复杂的操作两个更复杂的操作 (2)(2) 例 2-2: 两个有序表的归并 (merge) 操作 void MergeList(List La,List Lb,List & Lc){ // 非递减表 La,Lb 归并为非递减表 Lc InitList(Lc); i=j=1;k=0; La_len=ListLength(La); Lb_len=ListLength(Lb); // 指针平行移动,一次扫描完成

Page 15: 回顾:绪论( 1/2 )

两个更复杂的操作两个更复杂的操作 (3)(3) while((i<=La_len) && (j <= Lb_len)){ GetElem(La,i,ai);GetElem(Lb,j,bj); if (ai <= bj){ ListInsert(Lc,++k,ai);++i;} else {ListInsert(Lc,++k,bj);++j;} } //若 La 或 Lb 还有剩余部分,则直接把这些元素 // 依次加到 Lc 表尾 while (i<=La_len){ //La 有剩余 GetElem(La,i++,ai); Listinsert(Lc,++k,ai); }

Page 16: 回顾:绪论( 1/2 )

两个更复杂的操作两个更复杂的操作 (4)(4) while (j<=Lb_len){//Lb 有剩余 GetElem(Lb,j++,bji);Listinsert(Lc,++k,bj); }} //union 算法 2.2

时间复杂度分析: 算法的时间复杂度取决于 ADT List 定义中基本操作的执行时间

Page 17: 回顾:绪论( 1/2 )

如何表示线性表?如何表示线性表? 定义:将线性表中的元素相继存放在一个连续的存储空间中。

45 89 90 67 40 78

1 2 3 4 5 6

存储结构:类似一维数组特点:线性表的顺序存储方式——顺序表存取方式:顺序访问 , 可以随机存取

Page 18: 回顾:绪论( 1/2 )

顺序表的存储方式假设每个元素占用 l 个存储地址,则 LOC(a i+1) = LOC( a i )+ l

LOC(a i) = LOC(a1)+(i-1)*l

a1 a2 … a i … … … an

1 2 … i … … … n

a a+l … a+(i-1)*l … … … a+(n-1)*l idle

Page 19: 回顾:绪论( 1/2 )

创造我们自己的一维数组 (1/3)

假设 C语言中没有数组,你怎么实现数组?

#define LIST_INIT_SIZE 100 // 线性表存储空间初始分配量 #define LISTINCREMENT 10 // 存储空间分配增量

typedef struct { ElemType *elem; // 存储空间基址

int length; // 当前元素个数 ( 表长) int listsize; // 当前分配存储容量 // 以 sizeof(ElemType) 为单位 } SqList

Page 20: 回顾:绪论( 1/2 )

创造我们自己的一维数组 (2/3) 初始化 void 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; }

Page 21: 回顾:绪论( 1/2 )

按值查找::在顺序表中从头查找结点值等于给定值 x 的结点

int LocateElem ( SqList &L, ElemType x,equal ) {

int i = 0;

while ( i < L.length && L.elem[i] != x )

i++;

if ( i < L.length ) return ++i;

else return 0;

}

创造我们自己的一维数组 (3/3)

Page 22: 回顾:绪论( 1/2 )

求表的长度 int ListLength ( SqList L ) { return L.length; }

Page 23: 回顾:绪论( 1/2 )

提取函数::在表中提取第 i 个元素的值

Status GetElem( SqList L, int i ,ElemType &e) { if ( i >= 1 && i <= L.length ){ e= L.elem[i];return (OK);} else{ printf ( “ 参数 i 不合理! \n” ); return ERROR;} }

Page 24: 回顾:绪论( 1/2 )

插入元素

25 34 57 16 48 09 63

1 2 3 4 5 6 7

50插入 x

25 34 57 50 16 48 09 63

1 2 3 4 5 6 7 8

50

i

Page 25: 回顾:绪论( 1/2 )

Status ListInsert_Sq ( SqList &L, int i, ElemType e ) {// 在表 L中第 i 个位置前插入新元素 e

if (i < 1 || i > L.length+1 |) 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; }

顺序表的插入顺序表的插入

Page 26: 回顾:绪论( 1/2 )

q=&(L.elem[i-1]); //q 为插入位置for (p=&(L.elem[L.length-1]);p>=q;--p) *(p+1)=*p; // 插入位置及之后的元素右移}L.elem[i-1]=e;L.length--;

}

Page 27: 回顾:绪论( 1/2 )

性能分析: 基本操作为“移动” ( 实质为赋值)操作; 在第 i个位置前插入需移动 n-i+1 个元素 假设在任何位置插入元素都是等概率的,则移动次数

的期望值(平均次数) Eis 为

22

1)(

1)(

1

0)1(1

1)(

1

1=

1

nnn

n

nn

1inn

1n

i

Eis

因此,算法的平均时间复杂度为 O(n)

Page 28: 回顾:绪论( 1/2 )

删除元素

25 34 57 50 16 48 09 63 16

删除 x

25 34 57 50 48 09 63

1 2 3 4 5 6 7

1 2 3 4 5 6 7 8

Page 29: 回顾:绪论( 1/2 )

顺序表的删除 Status ListDelete_Sq ( SqList &L,int i, ElemType &e

) { // 在表 L 中删除第 i 个元素 , 并用 e 返回其值 if ((i<1) ||(i>L.length)) return ERROR; p=&(L.elem[i-1]); //p 为被删除元素的位置 e=*p; q=L.elem+L.length-1;// 表尾元素位置 for (++p;p<=q;++p) *(p-1)=*p;// 元素左移 --L.length; // 表长减一 return OK; }

Page 30: 回顾:绪论( 1/2 )

性能分析:基本操作为“移动” (赋值)操作;

删除第 i个位置的元素需(向左)移动 n-i 个元素假设在任何位置删除元素都是等概率的,则移动次数的期望值(平均次数) Edl 为

n

i

nnn

nin

n 1 2

1

2

1)(1)(

1=dlE

因此,算法的平均时间复杂度也为 O(n)!

Page 31: 回顾:绪论( 1/2 )

顺序表的应用顺序表的应用(( 11 ))集合的“并”运算void Union ( SqList &La, SqList Lb ) { int n = ListLength ( La); int m = ListLength ( Lb); for ( int i = 1; i <= m; i++ ) {

GetElem ( Lb, i,e ); // 在 Lb 中取一元素 if (!LocateElem(La,e,equal)) // La 中若没有

// 则向 La 表尾插入该元素 ListInsert_Sq(La,++n,e) ; } }时间复杂度: O(La.length* Lb.length)空间复杂度: O(La.length+ Lb.length)

Page 32: 回顾:绪论( 1/2 )

集合的“减”运算void Intersection ( SqList &La, SqList &Lb ) { int n = ListLength ( La); int m = ListLength ( Lb); for ( int i = 1; i <= m; i++ ) {

GetElem ( Lb, i,e ); // 在 Lb 中取一元素 if (k=LocateElem(La,e,equal)) // La 中若有

// 则从 La 中删除该元素 ListDelete_Sq(La,k,e) ; } }时间复杂度: O(La.length* Lb.length)空间复杂度: O(1)

顺序表的应用顺序表的应用(( 22 ))

Page 33: 回顾:绪论( 1/2 )

顺序表的应用顺序表的应用(( 33 )) 顺序表的归并 ( 算法 2.7)void MergeList_Sq(SqList La,SqList Lb,SqList &Lc) { pa=La.elem;pb=Lb.elem; Lc.listsize=Lc.length=La.length+Lb.length; pc=Lc.elem=(ElemType *) malloc(Lc.listsize * sizeof (ElemType)); if (!Lc.elem) exit(OVERFLOW); pa_last =La.elem+La.length-1; pb_last =Lb.elem+Lb.length-1;

Page 34: 回顾:绪论( 1/2 )

while (pa <=pa_last &&pb<=pb_last){ if (*pa<=*pb) *pc++=*pa++; else *pc++=*pb++; } while (pa<=pa_last) * pc++=*pa++; while (pb<=pb_last) * pc++=*pb++;}//MergeList_Sq

时间复杂度: O(La.length+Lb.length)O(La.length+Lb.length) 空间复杂度:空间复杂度: O(La.length+Lb.length)O(La.length+Lb.length)

Page 35: 回顾:绪论( 1/2 )

Homework 2 思考题: 试分析顺序表的插入与删除操作的最坏时间复杂

度。 作业: 习题集第 18页 题 2.21