《数据结构与算法》讲义
- 格式:doc
- 大小:553.54 KB
- 文档页数:31
《数据结构与算法》教学大纲
一、数据结构与算法教学大纲
数据结构与算法是计算机科学领域的基础,在计算机工程专业的学习和实践中有着重要的地位。
本课程旨在让学生掌握基本的数据结构、算法理论和实现技术,提高其计算机应用的能力。
1.数据结构
(1)线性结构
(a)线性表:顺序表、链表、栈、队列以及相关算法的实现分析
(b)稀疏矩阵的存储及算法
(c)串的基本操作及相关算法
(2)非线性结构
(a)树与二叉树:二叉树的存储、遍历及算法
(b)图:邻接表与邻接矩阵的存储方式,最短路径、最小生成树的求解
2.算法
(1)算法概念:算法的特征、分析及评价、设计的基本方法
(2)排序算法:冒泡排序、快速排序、折半插入排序、希尔排序及其它复杂度下的排序算法比较
(3)查找算法:二叉排序树、散列表及其它查找算法比较
(4)图算法:深度优先、广度优先等图算法
(5)贪心算法及其应用
(6)分治策略及应用
(7)动态规划及应用
3.数据结构和算法的应用
(1)图像处理和计算机视觉:图像缩放和滤波、边缘提取、轮廓绘制及相关算法。
数据结构与算法1. 数据结构数据结构是带结构的数据元素的集合。
(结构是指数据元素之间的关系)数据结构包含:逻辑结构:数据之间的逻辑关系物理结构(存储结构):数据元素及其关系在计算机内部的表示数据的运算和实现2. 逻辑结构线性结构:有且只有一个开始和一个终端结点,并且所有结点最多只有一个直接前驱和一个直接后继。
非线性结构:一个结点可能有多个直接前驱和直接后继;具体有集合结构,树形结构,图状结构。
3. 存储结构顺序存储结构:用一组连续的存储单元依次存储数据元素,数据元素之间的逻辑关系由元素的存储位置来表示。
优点:随机存取;缺点:只能使用相邻的一整块存储单元,可能产生较多外部水片。
链式存储结构:用一组任意的存储单元存储数据元素,数据元素之间的逻辑关系用指针来表示。
优点:不会产生碎片现象,能充分利用所有存储单元;缺点:每个元素因指针而占用额外的存储空间,只能实现顺序存储。
索引存储结构:在存储元素信息的同时,还建立附加的索引表。
优点:检索速度快;缺点:索引表占用额外的存储空间,增加和删除数据会修改索引表,耗时较多。
散列存储结构:根据元素的关键字直接计算出该元素的存储地址。
优点:检索、增加、删除结点操作很快;缺点:可能出现冲突,解决冲突会增加时间和空间开销。
4. 数据类型数据类型是一组性质相同的值的集合,以及定义于这个集合上的一组操作的总称。
在C语言中,声明了某个数据类型的变量,意味着规定了该变量的存储空间大小,以及能够执行的运算。
5. 抽象数据类型(A bstract D ata T ype, ADT)三要素<D, S, P>数据对象数据对象的关系集数据对象的操作集6. 算法算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每条指令表示一个或多个操作。
此外算法具有如下5个重要特性:有穷性:一个算法必须总在执行有穷不之后结束,且每一步都可在有穷时间内完成;确定性:算法中每条指令必须有确切的含义,对于相同的输入只得得到相同的输出;可行性:算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现;输入输出7. 算法效率的度量时间复杂度时间复杂度是指算法中基本运算的执行次数的数量级。
引言:数据结构与算法是计算机科学的核心领域,它们在现代计算机科学中起着至关重要的作用。
数据结构是组织和管理数据的方式,而算法则是解决问题的具体步骤。
本文将介绍数据结构与算法的基本概念、常见的数据结构和算法、它们的应用以及优化技巧。
概述:数据结构是计算机中组织和存储数据的方式。
它们可以是线性的,如数组和链表,也可以是非线性的,如树和图。
而算法则是解决问题的具体步骤和方法。
好的数据结构和算法可以提高程序的效率和性能,并节省计算机资源的使用。
正文内容:一、基本概念1.数据结构的定义和分类数据结构的定义和特点数据结构的分类:线性结构、非线性结构、存储结构2.算法的定义和特性算法的定义和特点算法的可行性和正确性二、常见的数据结构1.数组数组的定义和特点数组的操作和应用2.链表链表的定义和特点链表的种类和应用3.栈和队列栈和队列的定义和特点栈和队列的操作和应用4.树树的定义和特点常见的树结构:二叉树、平衡二叉树、B树、红黑树5.图图的定义和特点图的存储方法和常见的图算法三、常见的算法1.查找算法顺序查找二分查找散列表查找2.排序算法冒泡排序插入排序快速排序归并排序堆排序3.图算法广度优先搜索深度优先搜索最短路径算法最小树算法4.动态规划算法动态规划的定义和基本思想最优子结构和重叠子问题动态规划的应用领域5.贪心算法贪心算法的定义和基本思想贪心算法的一般步骤贪心算法的应用领域四、应用和优化1.数据结构和算法在数据库中的应用数据库索引的优化与算法选择数据库查询的优化和算法选择2.数据结构和算法在图形学中的应用三维图形的表示和渲染算法图形编辑和变换的算法3.数据结构和算法在网络和分布式系统中的应用网络协议的设计与实现分布式算法和数据分片的应用五、优化技巧1.空间复杂度和时间复杂度的优化空间复杂度的优化时间复杂度的优化2.常见的算法优化技巧剪枝技巧模拟退火算法遗传算法分支限界法近似算法总结:数据结构与算法是计算机科学中至关重要的领域。
《数据结构》实验课讲义实验一线性表基本操作的实现1.1单链表的运算1、建立单链表假设线性表中结点的数据类型是字符,我们逐个输入这些字符型的结点,并以换行符'\n'为输入条件结束标志符。
动态地建立单链表的常用方法有如下两种:(1)头插法建表①算法思路从一个空表开始,重复读入数据,生成新结点,将读入数据存放在新结点的数据域中,然后将新结点插入到当前链表的表头上,直到读入结束标志为止。
注意:该方法生成的链表的结点次序与输入顺序相反。
②具体算法实现LinkList CreatListF(void){//返回单链表的头指针char ch;LinkList head;//头指针ListNode *s; //工作指针head=NULL; //链表开始为空ch=getchar(); //读入第1个字符while(ch!='\n'){s=(ListNode *)malloc(sizeof(ListNode));//生成新结点s->data=ch; //将读入的数据放入新结点的数据域中s->next=head;head=s;ch=getchar(); //读入下一字符}return head;}(2)尾插法建表①算法思路从一个空表开始,重复读入数据,生成新结点,将读入数据存放在新结点的数据域中,然后将新结点插入到当前链表的表尾上,直到读入结束标志为止。
②具体算法实现LinkList CreatListR(void){//返回单链表的头指针char ch;LinkList head;//头指针ListNode *s,*r; //工作指针head=NULL; //链表开始为空r=NULL;//尾指针初值为空ch=getchar(); //读入第1个字符while(ch!='\n'){s=(ListNode *)malloc(sizeof(ListNode));//生成新结点s->data=ch; //将读入的数据放入新结点的数据域中if (head!=NULL)head=s;//新结点插入空表elser->next=s;//将新结点插到*r之后r=s;//尾指针指向新表尾ch=getchar(); //读入下一字符}//endwhileif (r!=NULL)r->next=NULL;//对于非空表,将尾结点指针域置空head=s;return head;}2.插入运算(1)思想方法插入运算是将值为x的新结点插入到表的第i个结点的位置上,即插入到ai-1与ai之间。
具体步骤:(1)找到ai-1存储位置p(2)生成一个数据域为x的新结点*s(3)令结点*p的指针域指向新结点(4)新结点的指针域指向结点ai。
(2)具体算法实现void InsertList(LinkList head,DataType x,int i){//将值为x的新结点插入到带头结点的单链表head的第i个结点的位置上ListNode *p;p=GetNode(head,i-1);//寻找第i-1个结点if (p==NULL)//i<1或i>n+1时插入位置i有错Error("position error");s=(ListNode *)malloc(sizeof(ListNode));s->data=x;s->next=p->next;p->next=s;}(3)算法分析算法的时间主要耗费在查找操作GetNode上,故时间复杂度亦为O(n)。
3.删除运算(1)思想方法删除运算是将表的第i个结点删去。
具体步骤:(1)找到ai-1的存储位置p(因为在单链表中结点ai的存储地址是在其直接前趋结点ai-1的指针域next中)(2)令p->next指向ai的直接后继结点(即把ai从链上摘下)(3)释放结点ai的空间,将其归还给"存储池"。
(2)具体算法实现void DeleteList(LinkList head,int i){//删除带头结点的单链表head上的第i个结点ListNode *p,*r;p=GetNode(head,i-1);//找到第i-1个结点if (p==NULL||p->next==NULL)//i<1或i>n时,删除位置错Error("position error");//退出程序运行r=p->next;//使r指向被删除的结点aip->next=r->next;//将ai从链上摘下free(r);//释放结点ai的空间给存储池}2.3.3循环链表(Circular Linked List)循环链表是一种首尾相接的链表。
1、循环链表(1)单循环链表——在单链表中,将终端结点的指针域NULL改为指向表头结点或开始结点即可。
(2)多重链的循环链表——将表中结点链在多个环上。
2、带头结点的单循环链表注意:判断空链表的条件是head==head->next;3、仅设尾指针的单循环链表用尾指针rear表示的单循环链表对开始结点a1和终端结点an查找时间都是O(1)。
而表的操作常常是在表的首尾位置上进行,因此,实用中多采用尾指针表示单循环链表。
带尾指针的单循环链表可见下图。
注意:判断空链表的条件为rear==rear->next;4、循环链表的特点循环链表的特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活。
【例】在链表上实现将两个线性表(a1,a2,…,an)和(b1,b2,…,bm)连接成一个线性表(a1,…,an,b1,…bm)的运算。
分析:若在单链表或头指针表示的单循环表上做这种链接操作,都需要遍历第一个链表,找到结点an,然后将结点b1链到an的后面,其执行时间是O(n)。
若在尾指针表示的单循环链表上实现,则只需修改指针,无须遍历,其执行时间是O(1)。
相应的算法如下:LinkList Connect(LinkList A,LinkList B){//假设A,B为非空循环链表的尾指针LinkList p=A->next;//①保存A表的头结点位置A->next=B->next->next;//②B表的开始结点链接到A表尾free(B->next);//③释放B表的头结点B->next=p;//④return B;//返回新循环链表的尾指针}注意:①循环链表中没有NULL指针。
涉及遍历操作时,其终止条件就不再是像非循环链表那样判别p或p->next是否为空,而是判别它们是否等于某一指定指针,如头指针或尾指针等。
②在单链表中,从一已知结点出发,只能访问到该结点及其后续结点,无法找到该结点之前的其它结点。
而在单循环链表中,从任一结点出发都可访问到表中所有结点,这一优点使某些运算在单循环链表上易于实现。
实验二栈、循环队列的简单应用2.1【例】在队列中依次加入元素a1,a2,…,an之后,a1是队头元素,an是队尾元素。
退出队列的次序只能是a1,a2,…,an。
(1)循环队列的基本操作循环队列中进行出队、入队操作时,头尾指针仍要加1,朝前移动。
只不过当头尾指针指向向量上界(QueueSize-1)时,其加1操作的结果是指向向量的下界0。
这种循环意义下的加1操作可以描述为:①方法一:if(i+1==QueueSize) //i表示front或reari=0;elsei++;②方法二--利用"模运算"i=(i+1)%QueueSize;(2)循环队列边界条件处理循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。
因此,无法通过条件front==rear来判别队列是"空"还是"满"。
【参见动画演示】解决这个问题的方法至少有三种:①另设一布尔变量以区别队列的空和满;②少用一个元素的空间。
约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空);③使用一个计数器记录队列中元素的总数(即队列长度)。
(3)循环队列的类型定义#define Queur Size 100 //应根据具体情况定义该值typedef char Queue DataType; //DataType的类型依赖于具体的应用typedef Sturet{ //头指针,队非空时指向队头元素int front; //尾指针,队非空时指向队尾元素的下一位置int rear; //计数器,记录队中元素总数DataType data[QueueSize]}CirQueue;(4)循环队列的基本运算用第三种方法,循环队列的六种基本运算:①置队空void InitQueue(CirQueue *Q){Q->front=Q->rear=0;Q->count=0; //计数器置0}②判队空int QueueEmpty(CirQueue *Q){return Q->count==0; //队列无元素为空}③判队满int QueueFull(CirQueue *Q){return Q->count==QueueSize; //队中元素个数等于QueueSize时队满}④入队void EnQueue(CirQueuq *Q,DataType x){if(QueueFull((Q))Error("Queue overflow"); //队满上溢Q->count ++; //队列元素个数加1Q->data[Q->rear]=x; //新元素插入队尾Q->rear=(Q->rear+1)%QueueSize; //循环意义下将尾指针加1 }⑤出队DataType DeQueue(CirQueue *Q){DataType temp;if(QueueEmpty((Q))Error("Queue underflow"); //队空下溢temp=Q->data[Q->front];Q->count--; //队列元素个数减1Q->front=(Q->front+1)&QueueSize; //循环意义下的头指针加1return temp;}⑥取队头元素DataType QueueFront(CirQueue *Q){if(QueueEmpty(Q))Error("Queue if empty.");return Q->data[Q->front];}2.2 链队列1、链队列的定义队列的链式存储结构简称为链队列。