关于数据结构的泛谈

声明:本文是在观看郝斌老师的数据结构系列视频后做的学习笔记,在此感谢郝斌老师

建议:本文适合对数据结构有一定学习基础的朋友参考,不建议新手阅读

PS:提到郝斌老师只是对无私的前辈心怀感激,并非广告

1.数据结构

狭义:

数据结构是专门研究数据存储问题的

数据的存储包含两个方面:个体的存储 + 个体关系的存储

从某个角度而言,数据存储最核心的问题是对个体关系的存储,个体的存储可以忽略不计

广义:

数据结构既包含数据的存储也包含对数据的操作

对存储的数据的操作就是算法

2.算法

狭义:

算法和数据的存储方式密切相关

广义:

算法和数据的存储结构无关

(也就是泛型的思想:对于同一种逻辑结构,无论该逻辑结构的物理存储是什么样子的,我们都可以对它执行相同的操作)

3.数据结构的分类

逻辑结构

      线性

           数组

           链表

           栈和队列是特殊的线性结构(操作受限)

      非线性

           树

           图

物理结构

      线性一维的连续单元(内存)

4.数据的存储结构

线性

      连续存储(数组)

           优点

                 存取速度很快

           缺点

                 插入、删除操作效率很低

                 事先必须知道数组的长度

                 需要大块连续的内存块

      离散存储(链表)

           优点

                 空间没有限制(不需要一块连续的内存)

                 插入、删除操作效率很高

           缺点

                 存取速度很慢

      线性结构的应用1  栈

           定义

                 一种可以实现“先进后出”的存储结构

           分类

                 静态栈

                 动态栈

           算法

                 出栈

                 压栈

           应用

                 函数调用(函数的嵌套)

                 中断

                 表达式求值

                 内存分配

                 缓冲处理

                 迷宫

      线性结构的应用2  队列

           定义

                 一种可以实现“先进先出”的存储结构

           分类

                 链式队列——用链表实现

                 静态队列——用数组实现,静态队列通常都是循环队列

           算法

                 入队

                 出队

           具体应用

                 所有和时间有关的操作都有队列的影子

【专题】递归

           定义

                 一个函数自己直接或间接调用自己

           栈与递归的实现

1.当在一个函数运行期间,调用另一个函数时,在运行被调函数之前,系统需要完成3件事:

将所有实参、返回地址等信息传给被调函数保存

给被调函数的局部变量(包括形参)分配存储区域

将控制转移到被调函数的入口

2.从被调函数返回调用函数之前,系统也需要完成3件工作:

保存被调函数的返回结果

释放被调函数所占的存储空间

依照被调函数保存的返回值地址,将控制转移给调用函数

PS:当多个函数迭代调用时,按照“后调用先返回”

(后进先出)的规则进行,上述函数之间的传递和控制转移必须借助栈来实现,所以,系统将整个程序运行所需的存储区域安排在一个栈中,每当调用一个函数时,就为它在栈顶分配一个存储区域,每当从一个函数退出时,就释放它的存储区域,则当前运行的函数的数据区域必须在栈顶。

3.递归需要满足的3个条件

1)递归必须要有一个明确的终止条件

2)该函数所处理的数据规模必须在递减

3)这个转化必须是可解的

4.循环和递归的关系

所有的循环都可以转化成递归,但用递归可以解决的问题不一定能用循环解决

递归

      易于理解

      速度慢

      所需存储空间大

循环

      不易理解

      速度快

      所需存储空间小

例子

      求阶乘

      求1+ 2 + 3 + 4 +…… + 100的和

      汉诺塔问题

      走迷宫

应用

      树和森林就是以递归方式定义的

      树和图的很多算法都是用递归来实现的

      很多数学公式就是以递归的方式定义的(如斐波那契数列)

非线性

           树

                 定义

                      专业定义(递归定义)

  1. 有且只有一个称为根的节点
  2. 有若干个互不相交的子树,这些子树本身也是一棵树

通俗定义

  1. 树由节点和边组成
  2. 每个节点只有一个父节点,但可以有多个子节点
  3. 但有一个节点例外,该节点没有父节点,该节点称为根节点

专业术语

      深度

           从根节点到最底层节点的层数称为深度(根节点是第一层)

      度

           某一节点的度是该节点下子节点的个数

                 分类

                      一般树

                            任意一个节点的子节点的个数都不受限制

                      二叉树

                            任意一个节点的子节点的个数最多两个,且子节点的位置不可更改

                            分类

                                  一般二叉树

                                  满二叉树

                                       在不增加树的层数的前提下,无法再添加一个节点的二叉树

                                  完全二叉树

                                       如果只删除了满二叉树最底层最右边的连续若干个节点,这样形成的二叉树就是完全二叉树

                      森林

                            n个互不相交的树的集合

                 存储

                      二叉树的存储

                            连续存储(完全二叉树,把一般二叉树补成完全二叉树)

                                  优点

                                       查找某个节点的父节点和子节点(判断有没有父、子节点)速度很快

                                  缺点

                                       耗用内存空间过大

                            链式存储

                      一般树的存储

                            双亲表示法(数组)

                            孩子表示法(边链表)

                            双亲孩子表示法(数组加边链表)

                            二叉树表示法(把一般树转换成二叉树来存储)

                      森林的存储

                            先把森林转换为二叉树,再存储二叉树

                 操作

                      遍历(遍历实质上是把非线性结构转化为线性结构的一种方式,以下三种遍历是三种不同的转化方式,并没有本质区别)

                            先序遍历(根、左、右)

                            中序遍历(左、根、右)

                            后序遍历(左、右、根)

                      已知两种遍历序列,求原始二叉树(已知任意一种序列不能推出原始二叉树,已知先中或者中后可以推出,已知先后不行)

                            具体方法参见视频71、72两节,在此不加详述

                 应用

                      树是数据库中数据组织的一种重要形式

                      操作系统子、父进程的关系本身就是一棵树

                      面向对象语言中类的继承关系本身就是一棵树

                      赫(哈)夫曼树

           图

                 (略)

5.排序

排序

      冒泡排序(相邻位置比较交换,每趟找出一个)

      插入排序(2和1比插入形成长度为2的序列A,3和A比插入形成长度为3的序列B,直至结束)

      选择排序(找出最大(小)的,与第一个位置的元素互换,在找出剩余元素中最大(小)的,与第二个位置的元素互换,直至结束)

      快速排序(先找出某一元素(一般取第一个元素)的最终位置,这时无序数列被分为两块,再分别对两块继续这样进行排序(递归),直至分成的两块长度为1)

           示例:

                            9<L>,0,8,10,-5,2,13,7<H>(需要两个指针L、H和一个中间变量temp = 9(第一个元素),假定L指向9,H指向7,先比较H所指向值与temp,H值大则向前移动H,直至H值小于temp时赋值:L值 = H值,H值视为垃圾数字,用“ * ”表示,若H值始终大于temp,则当L与H指向同一元素时一趟排序停止)

                            第一步:7<L>,0,8,10,-5,2,13,*<H>(7 < temp 赋值:L值 = H 值,7变成*,下一步移动L)

                            第二步:7,0,8,*<L>,-5,2,13,10<H>(0 < temp ,移动L,8 < temp ,移动L,10 > temp,赋值:H值 = L值,下一步移动H)

                            第三步:7,0,8,2<L>,-5,*<H>,13,10(13 > temp,移动H,2 < temp,赋值:L值 = H值,下一步移动L)

                            第四步:7,0,8,2,-5,9<L><H>,13,10(-5 < temp,移动L,L与H重合,得到temp 的最终位置,赋值:L值(H值) = temp,一趟排序结束)

                            PS:上述结果是一趟排序的结果(一趟结束条件:L与H重合),下一趟对7,0,8,2,-5用同样的方法排序(递归),下下一趟对13,10排序,直至所有待排序的无序列长度为1时,排序完成。

                                  H与L的移动规则:(本次)谁变(下一次)移谁

      归并排序(2个2个比,4个4个比,8个8个比,直至结束)

排序和查找的关系

      排序是查找的前提(也就是说排序是重点)

你可能感兴趣的:(数据结构)