用日常角度看数据结构和算法

12 篇文章 0 订阅
9 篇文章 0 订阅

有这么一个观点说,研究编程的程序员,做到最后都是数据结构和算法的研究。做了几年的编程以后的今天,觉得这个观点越来越有几分道理了。

原因:

  1. 计算机科学本来就是数学的一个分支,编程的难点和核心部分都是都是由数学算法作为基础

  2. 基础的数据结构都是存储数据在内存中,用算法调用和处理的数据。

  3. 计算机中对于数据结构和算法两者是分不开的,它们两者在内存交融处理计算。

本人高考数学考试不到一百分,是自己考砸了。至于原因不方便说,但是本人的数学基础还是挺好的,最近在温习高中数学,以方便研究数据结构和算法,在我们的工作中写算法不是光高中数学就可以的,很多还得有高等数学,尤其是线性代数,概率论,和微积分,但高中数学是它们的基础。程序中有很多出名的,有学术价值的算法都是在操作系统,和有关的程序引擎底层。举几个例子:游戏引擎,如unity3d,机器学习框架如tensorflow,计算机视觉框架如OpenCV。

    游戏引擎:比如:计算出模型是通过3D几何画图,模型表面的色彩和光照的渲染都是通过线性代数的矩阵来处理的。

   机器学习:比如:svm向量机处理数据,通过向量计算。

   计算机视觉:比如:图像的像素存储Mat是通过矩阵,美图美颜就是处理图像中Mat的存储的像素值。

 

我们来看看常用的数据结构:

参考博文:https://www.cnblogs.com/ysocean/p/7889153.html

一、数组

        数组就是可以在内存中存储多个元素的结构,其中的元素类型必须相同,而且在内存中连续的,数组的元素是通过数组的下标访问,不是从1开始,而是从0开始

    栗子:int [ ]  data  = new int[50];

                data[0] = 1; 

            它表示初始化了一个整型数组,数组名为data,数组长度是50,每个元素类型都是int型,在内存中的地址是连续的。并且赋值第一个元素为1。

        因为数组在存储数据时是按顺序存储的,存储数据的内存也是连续的,所以他的特点就是读取数据比较容易,插入和删除比较困难。简单解释一下为什么,在读取数据时,只需要告诉数组要从哪个位置(索引)取数据就可以了,数组会直接把你想要的位置的数据取出来给你。插入和删除比较困难是因为这些存储数据的内存是连续的,要插入和删除就需要变更整个数组中的数据的位置。

优点

1、按照索引查询速度快,遍历数组方便。

缺点:

1、数组只能存储一种类型的元素。

2、数组的大小定义完之后固定,无法扩容。

3、添加和删除的操作慢,因为数组内存地址是连续的,需要移动其他元素

适用于频繁查询,对存储空间要求不大,而且很少删除和增加元素的情况。

二、栈

        栈只允许在栈顶进行操作,栈底不允许操作。栈的特点是:先进后出,或者是后进先出。在栈顶放入元素的操作是入栈,取出元素的操作是出栈。

        栗子:栈的结构很像集装箱,越先放进去的东西,越晚才能拿出来,最后放进去的东西,最先拿出来。

三、链表

        链表是存储单元上不连续的的存储结构,数据元素的逻辑顺序是通过链表的指针地址来实现的。每个元素包含两个节点。一个节点是存储元素的数据域,另一个节点是指向下一个节点的指针域。根据指针的指向,可以行成不同的结构,例如:单链表,双向链表和循环链表。

        链表是由一系列的节点组成,这些节点不必在内存中连续,当添加和删除元素的时候,只需要改变相关节点的指针指向即可,效率很高。

        单链表:最后一个结点的指针域设置为空(NULL),作为链表的结束标志,表示它没有后继结点。

        双向链表:每个节点的指针域都有两个指针,分别指向它的后继和前驱,所以,从从任意节点开始,都能方便的访问它的前驱节点和后继节点。

        循环链表:从单链表可知,最后一个节点的指针域指向NULL,当我们将尾指针指向头结点,那么就形成了一个循环链表。

    优点:1、不需要初始化容量,可以任意增减元素。

               2、添加或者删除元素时,只需要改变前后两个元素的指针指向即可,删除和添加元素会很快。

    缺点:1、查找元素需要遍历链表来实现,很耗时。

               2、链表存在大量的指针域,占用空间大。

四、队列

        队列类似于栈,不同的是队列是在一端增加元素,在另一端取出元素,特点是:先入先出后入后出。放入元素的操作被称为入队,取出元素的操作被称为出队。

        栗子:队列的结构像是一根水管,从一个口入,另一个口出。

五、树

     上面的链表、队列、栈,都是线性表,因为其中每个数据元素只有一个前驱和一个后继,是一对 

一的关系。假如是一对多的关系呢?这种数据结构就是

      树是由n个(n>=0,n=0是,是一棵空树)有限节点构成的,是一个具有层次关系的集合。它看起来像是一棵倒挂的树,也就是说根朝上,而叶子朝下的。

      特点:1、每个节点具有零个或者多个子节点。

                 2、没有父节点的节点称为根节点。

                 3、每一个非根节点有且只有一个父节点。

                 4、除了根节点以外,每个子节点可分为多个不相交的子树。

      二叉树是树的一种,每个节点最多可具有两个子树,即结点的度最大为2(结点度:结点拥有的子树数)。

 

我们来看看常见的排序算法:

参考博文:https://www.cnblogs.com/eniac12/p/5329396.html

我们来看看常用的最小生成树算法:(作用于树型结构)

参考博文:https://blog.csdn.net/a2392008643/article/details/81781766

1.Kruskal算法

此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。 
1. 把图中的所有边按代价从小到大排序; 
2. 把图中的n个顶点看成独立的n棵树组成的森林; 
3. 按权值从小到大选择边,所选的边连接的两个顶点ui,viui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。 
4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。

 

2.Prim算法

此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。

  1. 图的所有顶点集合为VV;初始令集合u={s},v=V−uu={s},v=V−u;
  2. 在两个集合u,vu,v能够组成的边中,选择一条代价最小的边(u0,v0)(u0,v0),加入到最小生成树中,并把v0v0并入到集合u中。
  3. 重复上述步骤,直到最小生成树有n-1条边或者n个顶点为止。

 

 

我们来看看常用的最短路径算法:(作用于图型结构)

参考博文:

原文链接:https://blog.csdn.net/m0_37345402/article/details/76695930

Floyd-Warshall--只有五行的算法

求任意两个点之间的最短路程。 从i号顶点到j号顶点只经过前k号顶点的最短路程,这是一种动态规划的思想。

Dijkstra算法

——单源最短路径

 

每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。

 

1.把所有的顶点分为两部分:已知最短路程的顶点集合P和未知最短路径的顶点集合Q。 最开始,P集合中只有源点一个顶点,用visit[i]数组来记录哪些点在集合P。visit[i]=1表示这个顶点在P集合中,visit[i]=0表示这个顶点在Q集合中。

 

2.设置源点s到自己的最短路径为0,即dis[s]=0,若存在有源点能直接到达的顶点i,则把dis[i]设为e[s][i],同时把所有其他(源点不能到达的)顶点的最短路径设为inf。

 

3.在集合Q的所有顶点中选择一个离源点s最近的顶点u(dis[u]最小)加入到集合P,并考察所有以点u为起点的边,对每条边进行松弛操作。例如:存在一条u到v的边,通过u->v添加到尾部来拓展一条从s到v的路径,这条路径的长度是dis[u]+e[u][v]。如果它的值比目前已知的dis[v]的值要小,我们可以用新值来替代当前dis[v]中的值。

 

常见机器学习算法:(有浅入深)

参考博文:https://blog.csdn.net/qq_42379006/article/details/80741808

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Frank浩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值