数据结构与算法ch1Introduction_第1页
数据结构与算法ch1Introduction_第2页
数据结构与算法ch1Introduction_第3页
数据结构与算法ch1Introduction_第4页
数据结构与算法ch1Introduction_第5页
已阅读5页,还剩83页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

数据结构与算法DataStructuresandAlgorithmAnalysis信息工程学院SchoolofInformationEngineering教材(1)MarkAllenWeiss.

DataStructuresandAlgorithmAnalysisinC++,ThirdEdition,人民邮电出版社,2013.

(2)李春葆.《数据结构教程(第3版)》,清华大学出版社,2009.

References

(1)严蔚敏、吴伟民.《数据结构(C语言版)》,清华大学出版社,2006.

(2)张乃孝.《算法与数据结构-C语言描述(第3版)》,高等教育出版社,2012.(3)CliffordA.Shaffer.

DataStructuresandAlgorithmAnalysis,Edition3.2,电子工业出版社,2011.(电子版教材)第1章绪论

Chapter1Introduction1.1什么是数据结构(WhatisDataStructure)1.2算法(Algorithm)1.3算法分析(AlgorithmAnalysis)1.4数据结构+算法=程序(Program)本章小结(Summary)练习及上机(ExercisesandProjects)1.1.1数据结构的定义(DefinitionofDataStucture)1.1.2逻辑结构类型(LogicalStructureType)

1.1.3存储结构类型(PhysicalStructureType)1.1.4数据结构和数据类型

(DataStructureandDataType)1.1WhatisDataStructure1.1.1DefinitionofDataStucture数据(Data):所有能输入到计算机中并被计算机程序处理的符号的总称(包括数字、字符、声音、图像等信息)。数据类型(DataType):数据类型定义为:一个值的集合和定义在这个值集上的一组操作的总称。

数据元素(DataElement):能独立、完整地描述问题世界中的实体的最小数据单位称为数据元素(也称记录)。构成数据元素的不可分割的数据单位,称为数据项(也称字段)。数据对象(DataObject):性质相同的数据元素的集合,是数据的一个子集(如整数数据对象)。

Example:电信工程10级为一个学生数据对象,而其中的“张三”是一个数据元素。

Example1由4个整数组成的数据对象D1={20,-30,88,45}Example2由正整数组成的数据对象D2={1,2,3,...}Example3由26个字母组成的数据对象D3={A,B,C,...,Z}其中:D1,D3是有穷集,D2是无穷集。DataStructureincludes:

(1)数据元素之间的逻辑关系,即数据的逻辑结构(LogicalDataStructure)。(2)数据元素及其关系在计算机存储器中的存储方式,即数据的存储结构,也称为数据的物理结构(PhysicalDataStructure)。(3)施加在该数据上的操作,即数据的运算(DataOperation)。

数据结构(DataStructure):是指数据以及数据元素相互之间的联系。可以看作是相互之间存在着某种特定关系的数据元素的集合。因此,有时把数据结构看成是带结构的数据元素的集合。NoNameSexClassNo1张斌男99018刘丽女990234李英女990120陈华男990212王奇男990126董强男99025王萍女9901Table1.1studenttable

Example1.1

有一个学生表如表1.1所示。这个表中的数据元素是学生记录,每个数据元素由四个数据项(即学号、姓名、性别和班号)组成。

该表中的记录顺序反映了数据元素之间的逻辑关系(LogicalRelationship),用学号标识每个学生记录,这种逻辑关系可以表示为:

<1,8>,<8,34>,<34,20>,<20,12>,<12,26>,<26,5>

其中尖括号“<ai,ai+1>”表示元素ai和ai+1之间是相邻的,即ai在ai+1之前,ai+1在ai之后。

数据在计算机存储器中的存储方式就是存储结构(StorageStructure)。C/C++语言中,通常采用结构体数组和链表两种方式实现其存储结构。存放学生表的结构体数组(StructureArray)Stud定义为:

struct{ intno;/*存储学号*/ charname[8];/*存储姓名*/ charsex[2];/*存储性别*/ charclass[4];/*存储班号*/}Stud[7]={{1,“张斌”,“男”,“9901”},…,{5,"王萍","女","9901"}};结构体数组Stud各元素在内存中顺序存放,即第i(0≤i≤6)个学生对应的元素Stud[i]存放在第i+1个学生对应的元素Stud[i+1]之前,Stud[i+1]正好在Stud[i]之后。9901女王萍5…9901男张斌1Stud[0]Stud[6]Stud数组起始地址

存放学生表的链表(LinkedList)的结点类型StudType定义为:

typedefstructstudnode{ intno; /*存储学号*/ charname[8]; /*存储姓名*/ charsex[2]; /*存储性别*/ charclass[4]; /*存储班号*/ structstudnode*next;/*存储指向下一个学生的指针*/}StudType;链表首结点地址head1张斌男99018刘丽女990234李英女990120陈华男990212王奇男990126董强男99025王萍女9901∧

学生表构成的链表如右图所示。其中的head为第一个数据元素的指针。LinkedListofstudenttable

对于“学生表”这种数据结构,可以进行一系列的运算(operation),Forexample,insert,delete,query.从前面介绍的两种存储结构看到,同样的运算,在不同的存储结构中,其实现过程是不同的。

例如,查找学号为20的学生的姓名:对于Stud数组,可以从Stud[0]开始比较,Stud[0].no不等于20,再与Stud[1].no比较,…,直到Stud[3].no等于20,返回Stud[3].name。

对于head为首结点指针的链表,从head所指结点开始比较,head->no不等于20,从它的next得到下一个结点的地址,再与下一个结点的no域比较,…,直到某结点的no域等于20,返回其name域。

为了更确切地描述一种数据结构,通常采用二元组表示:

B=(K,R)其中,B是一种数据结构,它由数据元素的集合K和K上二元关系的集合R所组成。其中:K={ki|1≤i≤n,n≥0}R={rj|1≤j≤m,m≥0}

Representationoflogicalstructure:

其中:

ki表示集合K中的第i个结点或数据元素。n为K中结点的个数,特别地,若n=0,则K是一个空集,因而B也就无结构可言,有时也可以认为它具有任一结构。

rj表示集合R中的第j个二元关系(后面均简称关系)。m为R中关系的个数,特别地,若m=0,则R是一个空集,表明集合K中的元结点间不存在任何关系,彼此是独立的。

序偶<x,y>(x,y∈K)x为第一结点,y为第二结点。

x为y的直接前驱结点(通常简称前驱结点)

y为x的直接后继结点(通常简称后继结点)。

若某个结点没有前驱结点,则称该结点为开始结点;若某个结点没有后继结点,则称该结点为终端结点。说明:<x,y>表示有向关系,(x,y)表示无向关系。采用离散数学的表示方法。

例如,采用二元组表示例1.1的学生表。学生表中共有7个结点,依次用k1~k7表示,则对应的二元组表示为B=(K,R),其中:

K={k1,k2,k3,k4,k5,k6,k7} R={r}//只有一种关系 r={<k1,k2>,<k2,k3>,<k3,k4>,<k4,k5>,<k5,k6>,<k6,k7>}又例如,有如下数据即一个矩阵:

对应的二元组表示为B=(K,R),其中:K={2,6,3,1,8,12,7,4,5,10,9,11}R={r1,r2}其中,r1表示行关系,r2表示列关系r1={<2,6>,<6,3>,<3,1>,<8,12>,<12,7>,<7,4>,<5,10>,<10,9>,<9,11>}r2={<2,8>,<8,5>,<6,12>,<12,10>,<3,7>,<7,9>,<1,4>,<4,11>}一个二维数组1.1.2LogicalStructureType

由数据元素间关系的不同特性,有下列四类基本的结构:⑴集合结构。数据元素间的关系是“属于同一个集合”。集合是元素关系极为松散的一种结构。(Set)⑵线性结构。该结构的数据元素之间存在着一对一的关系。(LinearStructure)⑶树型结构。该结构的数据元素之间存在着一对多的关系。(Tree)⑷图形结构。该结构的数据元素之间存在着多对多的关系,图形结构也称作网状结构。(Graph)1.1.2LogicalStructureType

(1)集合(Set)如果数据结构中,数据元素之间不考虑关系问题(无前驱/后继之分),则称这种结构为集合。在集合中,各元素是“平等”的,它们的共同关系是:都属于同一个集合,无其他关系。集合结构

(2)线性结构(LinearStructure)

结点之间关系:一对一(OnetoOne)

特点:开始结点和终端结点都是惟一的,除了开始结点和终端结点以外,其余结点都有且仅有一个前驱结点,有且仅有一个后继结点。顺序表就是典型的线性结构。…1.1.2LogicalStructureType

Example1L=(20,-5,66,15,44)是一个线性表Example2一张登记表DL序号姓名性别年龄

1李刚男25记录12王霞女29记录23刘大海男40记录34李爱林男44记录4其中:姓名、性别、年龄是数据项(item)、数据域(field);(姓名,性别,年龄)是记录(record),C语言将"记录"(record)定义为”结构”(struct);登记表也是一个线性表。

(3)树形结构(Tree)

结点之间关系:一对多(OnetoMany)

特点:开始结点唯一,终端结点不唯一。除终端结点以外,每个结点有一个或多个后续结点;除开始结点外,每个结点有且仅有一个前驱结点。例3家族中父子关系是一种层次结构--树T

张一张三张二一张三一张三小张三大

张二张四层次结构:部门之间的隶属关系:学校->系->科->班领导和被领导之间领导关系:主席->部长->司长->处长->科长

(4)图形结构(Graph)

结点之间关系:多对多(ManytoMany)

特点:没有开始结点和终端结点,所有结点都可能有多个前驱结点和多个后继结点。例4无向图G

ABDCEFG其中:A、B、C等是顶点(vertex),图中任意两个顶点之间都可能有关系。网络结构:电网,电信网,计算机通信网等。1.1.3存储结构类型(PhysicalStructureType)

数据结构在计算机中的存储方式。

两方面:内容存储:数据结构中的各数据元素的内容(数据),都分别存储在一个独立的可访问的存储区中;关系存储:数据元素的存放方式方法,必须能显示地或隐式地体现数据元素间的逻辑关系。(2)链式存储方法

(LinkedStorage)(3)索引存储方法(IndexingStorage)

(4)散列存储方法(HashStorage)1.1.3PhysicalStructureType(1)顺序存储方法(SequentialStorage)(1)顺序存储(SequentialStorage)这是一种主要面向线性关系的存储方法。对线性数据结构,可将其数据元素,按相应的线性关系下的前后次序,存储在物理存储器中,使得数据元素在此线性关系下的逻辑次序与它们在存储器中的存放次序一致。这种存储方式称为顺序方法(也称连续方法)。数据元素之间的线性关系由它们的存储次序体现,而不需要专门存储。1.1.3PhysicalStructureType(2)链式存储(LinkedStorage)

每个数据元素的存储区分两大部分,第一部分为数据区,存储元素的内容;第二部分为指针区。

(存放该数据元素与其它数据元素之间的关系信息,这种关系信息一般为地址)

通常要借助于程序语言的指针类型来描述。1.1.3PhysicalStructureType(3)索引存储(IndexingStorage)

索引存储是面向检索操作。在存储结点信息的同时还建立附加的索引表。表中的每一项称为索引项。索引项的一般形式:(关键字,地址)关键字是能唯一标识一个结点的那些数据项。优点:检索速度快。缺点:增加额外的索引表,占用较多的存储空间。1.1.3PhysicalStructureType(4)散列存储(HashStorage)

散列存储(也称杂凑法)是一种按元素内容存储元素的方法。其基本思想是:设置一个函数,称为散列函数:元素内容地址;规定元素内容到存储地址的映射;存储时,通过散列函数求出元素对应的存储地址,按此地址存储;读取时,通过散列函数求出元素的存储地址,按此地址读取。1.1.3PhysicalStructureType上述四种基本存储方法,既可以单独使用,也可以组合起来对数据结构进行存储映像。同一种逻辑结构采用不同的存储方法,可以得到不同的存储结构。选择何种存储结构来表示相应的逻辑结构,视具体要求而定,主要考虑的是运算方便及算法的时空要求。1.1.3PhysicalStructureType

(1)数据类型(DataType)

高级程序语言中,一般须对程序中出现的每个变量、常量或表达式,明确说明它们所属的数据类型。不同类型的变量,其所能取的值的范围不同,所能进行的操作不同。

数据类型是一个值的集合和定义在此集合上的一组操作的总称。1.1.4DataStructureandDataType

如C/C++中的int就是整型数据类型。它是所有整数的集合(在16位计算机中为-32768~32767的全体整数)和相关的整数运算(如+、-、*、/等)。

(2)抽象数据类型(AbstractDataType)

抽象数据类型(AbstractDataType简写为ADT)指的是用户进行软件系统设计时从问题的数学模型中抽象出来的逻辑数据结构和逻辑数据结构上的运算,而不考虑计算机的具体存储结构和运算的具体实现算法。

抽象数据类型=数据元素集合+抽象运算例如,抽象数据类型复数的定义:ADTComplex{数据对象(DataObject):

D={e1,e2|e1,e2均为实数}数据关系(DataRelation):

R1={<e1,e2>|e1是复数的实数部分,e2是复数的虚数部分}e1+e2i基本操作(BasicOperation):

AssignComplex(&Z,v1,v2):构造复数Z。DestroyComplex(&Z):复数Z被销毁。GetReal(Z,&real):返回复数Z的实部值。GetImag(Z,&Imag):返回复数Z的虚部值。Add(z1,z2,&sum):返回两个复数z1,z2的和。}ADTComplex1.2算法(Algorithm)1.2.1什么是算法(WhatisAlgorithm)

1.2.2算法描述(AlgorithmDescription)

数据元素之间的关系有逻辑关系和物理关系,对应的操作有逻辑结构上的操作功能和具体存储结构上的操作实现。通常把具体存储结构上的操作实现步骤或过程称为算法。1.2.1什么是算法(WhatisAlgorithm)

算法的五个重要的特性

(1)有穷性:在有穷步之后结束。(2)确定性:无二义性。

(3)可行性:可通过基本运算有限次执行来实现。(4)有输入

(5)有输出

例如:确定性:无二义性。例.{x=5;y=10;z=x+++y;printf(“%d,%d,%d”,x,y,z);}x+++y解释为:x+(++y)?(x++)+y?Example1.2考虑下列两段描述:(1)描述一 voidexam1() { n=2; while(n%2==0) n=n+2; printf("%d\n",n); }

(2)描述二 voidexam2() { y=0; x=5/y; printf(“%d,%d\n”,x,y); }

这两段描述均不能满足算法的特征,试问它们违反了哪些特征?

解:(1)算法是一个死循环,违反了算法的有穷性特征。(2)算法包含除零错误,违反了算法的可行性特征。

本书中采用C/C++语言描述算法。说明:C++语言中提供了一种引用运算符“&”,引用是别名,当建立引用时,程序用另一个已定义的变量或对象(目标)的名字初始化它;从那时起,引用作为目标的别名而使用,对引用的改动实际就是对目标的改动。注意:TurboC不支持引用类型。1.2.2算法描述(AlgorithmDescription)“引用”的概念例如:inta=4; /*a为普通的整型变量*/int&b=a;/*b是a的引用变量*/这里说明b变量是变量a的引用,b也等于4,之后这两个变量同步改变。当a改变时b也同步改变,同样,当b改变时a也同步改变。1.2.2AlgorithmDescriptionmain(){

inta=2;int&b=a;printf("a=%d,b=%d\n",a,b);/*输出:a=2,b=2*/

b++;printf("a=%d,b=%d\n",a,b);/*输出:a=3,b=3*/

a++;printf("a=%d,b=%d\n",a,b);/*输出:a=4,b=4*/}引用与指针的区别

引用常用于函数形参中,采用引用型形参时,在函数调用时将形参的改变回传给实参。例如,有如下函数(其中的形参均为引用型形参):

voidswap(int&x,int&y){inttmp=x;x=y;y=tmp;}当用执行语句swap(a,b)时,a和b的值发生了交换。1.3算法分析(AlgorithmAnalysis)

1.3.1算法时间复杂度分析(TimeComplexityAnalysisofAlgorithm)

1.3.2算法空间复杂度分析

(SpaceComplexityAnalysisofAlgorithm)

一个算法是由控制结构(顺序、分支和循环三种)和原操作(指固有数据类型的操作)构成的,则算法时间取决于两者的综合效果。控制语句1原操作控制语句n原操作…一个算法1.3.1算法时间复杂度分析(TimeComplexityAnalysisofAlgorithm)

同一问题可以采用多种算法实现。如何比较算法执行效率?

•算法描述的语言不同

•算法执行的环境不同•其他因素

所以不能用绝对执行时间进行比较

为了便于比较同一问题的不同算法,通常从算法中选取一种对于所研究的问题来说是基本运算的原操作(以下将基本运算的原操作简称为基本运算)。算法执行时间大致为基本运算所需的时间与其运算次数(也称为频度)的乘积。被视为算法基本运算的一般是最深层循环内的语句。

在一个算法中,进行基本运算的次数越少,其运行时间也就相对地越少;基本运算次数越多,其运行时间也就相对地越多。所以,通常把算法中包含基本运算次数的多少称为算法的时间复杂度,也就是说,一个算法的时间复杂度是指该算法的基本运算次数。

算法中基本运算次数T(n)是问题规模n的某个函数f(n),记作:T(n)=O(f(n))

记号“O”读作“大O”(big-Oh),它表示随问题规模n的增大算法执行时间的增长率和f(n)的增长率相同。“O”的形式定义为:

若f(n)是正整数n的一个函数,则T(n)=O(f(n))表示存在一个正的常数M,使得当n≥n0时都满足:|T(n)|≤M|f(n)|

也就是只求出T(n)的最高阶,忽略其低阶项和常系数,这样既可简化T(n)的计算,又能比较客观地反映出当n很大时,算法的时间性能。例如,T(n)=3n2-5n+10000=O(n2)本质上讲,是一种最高数量级的比较

一个没有循环的算法的基本运算次数与问题规模n无关,记作O(1),也称作常数阶。

一个只有一重循环的算法的基本运算次数与问题规模n的增长呈线性增大关系,记作O(n),也称线性阶。

其余常用的还有平方阶O(n2)、立方阶O(n3)、对数阶O(log2n)、指数阶O(2n)等。

各种不同数量级对应的值存在着如下关系:O(1)<O(log2n)<O(n)<O(n*log2n)<O(n2)<O(n3)<O(2n)<O(n!)

Example1.4

求两个n阶方阵的相加C=A+B的算法如下,分析其时间复杂度。#defineMAX20/*定义最大的方阶*/voidmatrixadd(intn,intA[MAX][MAX],intB[MAX][MAX],intC[MAX][MAX]){ inti,j; for(i=0;i<n;i++) for(j=0;j<n;j++) C[i][j]=A[i][j]+B[i][j];}

该算法中的基本运算是两重循环中最深层的语句C[i][j]=A[i][j]+B[i][j],分析它的频度,即:

T(n)==O(n2)Example1.5Giveananalysisoftherunningtimeintfun(intn){inti,j,k,s;s=0;for(i=0;i<=n;i++)for(j=0;j<=i;j++) for(k=0;k<=j;k++)s++;return(s);}基本语句或基本操作

解:该算法的基本操作是语句s++,其频度:T(n)==O(n3)则该算法的时间复杂度为O(n3)。Example1.6Giveananalysisoftherunningtime

voidfunc(intn){inti=0,s=0;while(s<n){i++; s=s+i;}}基本语句

解:对于while循环语句,设执行的次数为m,i从0开始递增1,直到m为止,有:s=0+1+2+…+m-1=m(m-1)/2,并满足s=m(m-1)/2<n,则有m<。T(n)=O()所以,该算法的时间复杂度为O()。

Example1.7

有如下算法:voidfun(inta[],intn,intk)/*数组a共有n个元素*/{ inti; if(k==n-1) for(i=0;i<n;i++) printf("%d\n",a[i]); else {for(i=k;i<n;i++) a[i]=a[i]+i*i; fun(a,n,k+1); }}调用上述算法的语句为fun(a,n,0),求其时间复杂度。解:设fun(a,n,0)的时间复杂度为T(n),则fun(a,n,k)的执行时间为T1(n,k),由fun()算法可知:

T1(n,k)=n 当k=n-1时T1(n,k)=(n-k)+T1(n,k+1)其他情况

则T(n)=T1(n,0)=n+T1(n,1)=n+(n-1)+T1(n,2)=…=n+(n-1)+…+2+T1(n,n-1)=n+(n-1)+…+2+n=O(n2)所以调用fun(a,n,0)的时间复杂度为O(n2)。

空间复杂度是对一个算法在运行过程中临时占用的存储空间大小的量度,一般也作为问题规模n的函数,以数量级形式给出,记作:S(n)=O(g(n))

若所需额外空间相对于输入数据量来说是常数,则称此算法为原地工作。若所需存储量依赖于特定的输入,则通常按最坏情况考虑。1.3.2算法空间复杂度分析

(SpaceComplexityAnalysisofAlgorithm)Example1.8分析例1.4和例1.5的空间复杂度。解:由于这两个算法中临时变量的个数与问题规模n无关,所以空间复杂度均为O(1)。1.4数据结构+算法=程序DataStructure+Algorithm=program

数据结构对算法的影响主要在两方面(1)数据结构的存储能力

数据结构存储能力强、存储信息多=>算法将需要较好设计(时间少),存储空间大。时间和空间的平衡(2)定义在数据结构上的操作

在数据结构上定义基本操作=>算法调用这些基本操作。基本操作越完整,算法设计就越容易算法基本操作基本算法应用程序应用程序是通过调用基本算法实现的选择数据结构需要考虑的几个方面:(1)数据结构要适应问题的状态描述(2)数据结构应与所选择的算法相适应(3)数据结构的选择同时要兼顾程序设计的方便(4)灵活应用已有知识Example:有若干学生数据(学生数小于50),每个学生数据包含学号(每个学生学号是惟一的,但学生记录不一定按学号顺序存放)、姓名、班号和若干门课程成绩(每个学生所选课程数目可能不等,但最多不超过6门)。要求设计一个程序输出每个学生的学号、姓名和平均分以及每门课程(课程编号从1~6)的平均分。Solution1:将学生的全部数据项放在一个表中,一个学生的全部数据对应一条记录。由于课程最多可选6门,对应的成绩项也应有6个。对应的数据结构如下:structstud{ intno; /*学号*/ charname[10]; /*姓名*/ intbno; /*班号*/ intdeg1; /*课程1分数*/ intdeg2; /*课程2分数*/ intdeg3; /*课程3分数*/ intde

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论