算法与数据结构

[数据结构与算法 03] 最好、最坏、平均、均摊 时间复杂度

荒凉一梦 提交于 2020-02-09 01:29:34
由来 /**** 在一个无序的数组(array)中 查找变量 x 第一次出现的位置。如果没有找到,就返回 -1 ****/ // n 表示数组array的长度 int find(int[] array, int n, int x) { int i = 0; int pos = -1; for (; i < n; ++i) { if (array[i] == x) pos = i; } return pos; } 分析出此函数的时间复杂度为 O(n) 在数组中查找一个数据,并不需要每次都把整个数组都遍历一遍, 因为有可能中途找到就可以提前结束循环了。 所以我们可以这样优化一下这段查找代码 /**** 在一个无序的数组(array)中 查找变量 x 第一次出现的位置。如果没有找到,就返回 -1 ****/ // n 表示数组array的长度 int find(int[] array, int n, int x) { int i = 0; int pos = -1; for (; i < n; ++i) { if (array[i] == x) { pos = i; break; // 已经找到了,就不必继续找了 } } return pos; } 那么问题来了,如此优化以后,时间复杂度还是 O(n) 吗??? 可能第一次就找到了,只循环了一次,那时间复杂度就是 O(1)

数据结构 耿国华老师讲

依然范特西╮ 提交于 2020-02-08 22:05:38
第一章$绪论 第一讲$数据结构的基础 数据是表征客观事物的可记录可识别的符号集合。数据是信息处理的核心基础。 数据结构有关的基本概念术语: 1.数据 2.数据元素 3.数据对象 4.数据类型 5.数据类型 6.抽象数据类型 7.数据结构 数据结构是指相互之间存在一种或多种特定关系的数据元素集合。它强调的是带有结构的数据元素的集合,数据元素之间的相互关系,即数据的组织形式。数据的组织方法与效率密切相关,采用不同数据的组织方法其处理效率不同。 第二讲$数据结构的内容简介 数据结构的内容,即数据结构研究范围:逻辑结构、存储结构、运算集合。数据结构注重的是数据元素之间的相互关系。 数据元素的相互关系表示为数据元素间的逻辑关系即逻辑结构。数据元素之间存在四种基本的逻辑结构: 1.集合结构 2.线性结构 3.树形结构 4.图形结构 数据元素之间关系在计算机中的表示方法分为: 顺序映象 (顺序存储结构,如数组,就是一组连续配置的单元); 非顺序映象 (非顺序存储结构,如链表,是一组任意配置的单元,通过指针连接起来,维持逻辑关系)。 第三讲$数据结构与C语言…… 一本正经划水总结一下(咳咳) 当需要用一个形式参数直接改变对应实参的值时,改形式参数应说明为:与实参同类型指针参数。 第四讲$算法性能评价 算法性能评价指标算法的执行时间,和占用空间两个方面,通过引入问题规模,语句频度等概念

『嗨威说』数据结构 - 第三章学习内容小结

删除回忆录丶 提交于 2020-02-08 09:37:43
本文内容: 本章内容小结 完成作业或实践时解决困难的经验分享 参考资料、说明推荐理由及列出相关链接(或书目名称,具体页码) 目前学习过程中存在的困难,待解决或待改进的问题 接下来的目标 一、本章内容小结:(栈与队列)   (1)基本概念: 栈(Stack): 只允许在一端进行插入或删除操作的线性表。首先栈是一种线性表,但是限定这种线性表只能在某一端进行插入和删除操作 栈顶(top): 线性表允许进行插入和删除的那一端。(开口的那一端) 栈底(bottom): 固定的,不允许进行插入和删除的另一端。(封死的那一端) 空栈: 不含任何元素的空表。 栈的两种表示方式: 栈的本质是线性表,那么它就同样有线性表的两种表示形式:顺序栈 和 链式栈(简称“链栈”) 两者的区别:存储的数据元素在物理结构上是否是相互紧挨着的。顺序栈存储元素预先申请连续的存储单元;链栈需要即申请,数据元素不紧挨着。 栈的“上溢”和“下溢”问题: “上溢”:在栈已经存满数据元素的情况下,如果继续向栈内存入数据,栈存储就会出错。(栈满还存会“上溢”) “下溢”:在栈内为空的状态下,如果对栈继续进行取数据的操作,就会出错。(栈空再取会“下溢”) 对于栈的两种表示方式来说,顺序栈两种情况都有可能发生;而链栈由于“随时需要,随时申请空间”的存储结构,不会出现“上溢”的情况。 栈的基本操作:   InitStack(&S)

数据结构与算法(排序算法稳定性)

送分小仙女□ 提交于 2020-02-08 04:01:38
排序与搜索 排序算法(英语:sorting algorithm)是一种能将一串数据依照特定顺序进行排列的一种算法。 排序算法的稳定性 **稳定性:**稳定排序算法会让原本有相等键值的记录维持相对次序,也就是如果一个排序算法是稳定的,当有两个相等键值的记录R和S,且在原本的列表种R出现在S之前,在排序过的列表中R也会在S之前。 当相等的元素是无法分辨的,比如像是整数,稳定性并不是一个问题。然而,假设以下的数对将要以他们的第一个数字来排序。 (4,1) ,(3,1),(3,7),(5,6) 在这个情况下,有可能产生两种不同的结果,一个是让相等键值的记录维持相对的次序,而另外一个则没有: (3,1),(3,7),(4,1) ,(5,6) (维持次序) (3,7),(3,1),(4,1), (5,6) (次序被改变) 不稳定排序算法可能会在相等的键值中改变记录的相对次序,但是稳定排序算法从来不会如此,不稳定排序算法可以被特别的实现为稳定。做这件事情的一个方式是人工扩充键值的比较,如此在其他方面相同键值的两个对象之间比较,(比如上面的比较中加入第二个标准,第二个键值的大小)就会被决定使用在原先数据次序中的条目,当作一个同分决赛。然而要记住这种次序通常牵涉到额外的空间负担。 来源: CSDN 作者: 阴天了 链接: https://blog.csdn.net/sun_xiao_kai

【Python数据结构与算法笔记day36】7.2. 二叉树的遍历+深度优先遍历+ 广度优先遍历(层次遍历)

吃可爱长大的小学妹 提交于 2020-02-07 10:36:43
文章目录 7.2. 二叉树的遍历 二叉树的遍历 深度优先遍历 广度优先遍历(层次遍历) 7.2. 二叉树的遍历 二叉树的遍历 树的遍历是树的一种重要的运算。所谓遍历是指对树中所有结点的信息的访问,即依次对树中每个结点访问一次且仅访问一次,我们把这种对所有节点的访问称为遍历(traversal)。那么树的两种重要的遍历模式是深度优先遍历和广度优先遍历, 深度优先一般用递归,广度优先一般用队列。一般情况下能用递归实现的算法大部分也能用堆栈来实现。 深度优先遍历 对于一颗二叉树,深度优先搜索(Depth First Search)是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。 那么深度遍历有重要的三种方法。这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。这三种遍历分别叫做先序遍历(preorder),中序遍历(inorder)和后序遍历(postorder)。我们来给出它们的详细定义,然后举例看看它们的应用。 先序遍历 在先序遍历中,我们先访问根节点,然后递归使用先序遍历访问左子树,再递归使用先序遍历访问右子树 根节点->左子树->右子树 def preorder ( self , root ) : """递归实现先序遍历""" if root == None : return print root . elem self . preorder (

[数据结构与算法]第6章 递归

偶尔善良 提交于 2020-02-07 02:28:41
个人博客文章地址 文章目录 6.1 递归需要遵守的重要规则 6.2 递归-迷宫问题 6.3 递归-八皇后问题(回溯算法) 6.1 递归需要遵守的重要规则 执行一个方法时,就创建一个新的受保护的独立空间(栈空间) 方法的局部变量是独立的,不会相互影响, 比如n变量 如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据. 递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError,死龟了:) 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。 6.2 递归-迷宫问题 说明: 小球得到的路径,和程序员设置的找路策略有关即:找路的上下左右的顺序相关 再得到小球路径时,可以先使用(下右上左),再改成(上右下左),看看路径是不是有变化 测试回溯现象 思考: 如何求出最短路径? 代码实现: public class MiGong { public static void main ( String [ ] args ) { // 先创建一个二维数组,模拟迷宫 // 地图 int [ ] [ ] map = new int [ 8 ] [ 7 ] ; // 使用1 表示墙 // 上下全部置为1 for ( int i = 0 ; i < 7 ; i ++ ) { map

数据结构与算法(双向链表)

老子叫甜甜 提交于 2020-02-06 22:13:34
一种更复杂的链表叫“双向链表”或者“双面链表”,每个节点有两个链接,一个指向前一个节点,当此节点为第一个节点时,指向空值;而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。 操作实现 class Node(object): """节点类""" def __init__(self, item): self.elem = item self.prev = None self.next = None class DoubleLinkList(object): """双链表""" def __init__(self, node=None): self._head = node def is_empty(self): return self._head is None def length(self): """链表长度""" #cur游标,用来移动遍历节点 cur = self._head #count记录数量 count = 0 while cur != None: count = count + 1 cur = cur.next return count def travel(self): """遍历整个链表""" #cur游标,用来移动遍历节点 cur = self._head #count记录数量 while cur != None: print(cur.elem,end=

数据结构——红黑树

别来无恙 提交于 2020-02-06 18:37:38
文章目录 1 引言 2 定义 定义节点名称: 3 性质 4 2-3-4树和红黑树的等价关系 5 查找 6 插入 6.1(情景3) 插入节点的父节点为黑色 6.2(情景4) 插入节点的父节点为红色,叔叔节点为黑色 6.2.1(情景4.2.1) 父节点P为G左孩子,插入位置为左孩子 6.2.2(情景4.2.2) 父节点P为G左孩子,插入位置为右孩子 6.2.3(情景4.3.1) 父节点P为G右孩子,插入位置为右孩子 6.2.4(情景4.3.2) 父节点P为G右孩子,插入位置为左孩子 6.3(情景4.1) 插入节点的父节点为红色,叔叔节点为红色 6.3.1(情景4.1) 插入位置为左子树 6.3.2(情景4.1) 插入位置为右子树 7 删除 删除情景1:替换结点是红色结点 7.1 删除红色叶子节点 7.2 删除红色节点,只有左子树或只有右子树 7.3 删除红色节点,既有左子树又有右子树 7.4 删除的黑色节点仅有左子树或者仅有右子树 7.5 删除黑色的叶子节点 8 总结 9 思考题和习题答案 思考题1:黑结点可以同时包含一个红子结点和一个黑子结点吗? 习题1:请画出图15的插入自平衡处理过程。 习题2:请画出图29的删除自平衡处理过程。 推荐阅读 1 引言 红黑树 是 树 的 数据结构 中最为重要的一种。 Java 的容器 TreeSet 、 TreeMap 均使用 红黑树 实现。

[数据结构与算法]第4章 链表

谁说我不能喝 提交于 2020-02-06 12:40:34
个人博客文章地址 文章目录 4.1 单向环形链表应用场景 4.1.1 Josephu(约瑟夫、约瑟夫环) 问题 4.1 单向环形链表应用场景 4.1.1 Josephu(约瑟夫、约瑟夫环) 问题 Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。 提示:用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。 约瑟夫问题-创建环形链表的思路图解 约瑟夫问题-小孩出圈的思路分析图 代码实现: public class Josepfu { public static void main ( String [ ] args ) { // 测试一把看看构建环形链表,和遍历是否ok CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList ( ) ; circleSingleLinkedList . addBoy ( 125 ) ; //

数据结构之算法时间复杂度

半城伤御伤魂 提交于 2020-02-06 05:30:39
原文链接 算法的时间复杂度定义为: 在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记作:T(n}=0(f(n))。它表示随问题规模n的增大,算法执行时间的埔长率和 f(n)的埔长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中f( n)是问题规横n的某个函数。 根据定义,求解算法的时间复杂度的具体步骤是: 找出算法中的基本语句   算法中执行次数最多的那条语句就是基本语句,通常是最内层循环的循环体。 计算基本语句的执行次数的数量级   只需计算基本语句执行次数的数量级,这就意味着只要保证基本语句执行次数的函数中的最高次幂正确即可,可以忽略所有低次幂和最高次幂的系数。这样能够简化算法分析,并且使注意力集中在最重要的一点上:增长率。 用大Ο记号表示算法的时间性能   将基本语句执行次数的数量级放入大Ο记号中。 如何推导大o阶呢?我们给出了下面 的推导方法: 1.用常数1取代运行时间中的所有加法常数。 2.在修改后的运行次数函数中,只保留最髙阶项。 3.如果最高阶项存在且不是1,则去除与这个项相乘的常数。 简单的说,就是保留求出次数的最高次幂,并且把系数去掉。 如T(n)=2n^2+n+1 =O(n^2) 例如: #include "stdio.h" int main