数据结构与算法原理基本关系和原理
Posted 一只写诗的程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法原理基本关系和原理相关的知识,希望对你有一定的参考价值。
在计算机科学中,数据结构(英语:data structure)是计算机中存储、组织数据的方式。---来自维基百科
那我们计算机中有哪些常见的数据结构了?数据结构与算法又有什么关系?数据结构和计算机底层联系是否非常紧密?基于这些问题,同时为了方便的理解数据结构,我们尽量使用高级一些的语言(python、Java、C++、C)虽然数据结构与堆栈、甚至用汇编中的概念会更深入理解一点,但实际上我们实践操作是不需要这么深入了解到这么细致的。(当然这里我会将汇编和各种高级语言混合在一起进行操作,这样的话,理解起来就轻松一点,强调一点,写博客喜欢从原理性的东西说起,所以要是有大佬精通这一块的跳过,或者指出错误,(* ̄) ̄))
首先我们假设在python中写了如下程序(这里会将python 中的程序用汇编解释):
import numpy as np #小明给了你50块钱,小红给了你7块... getMoney=[50,7,20,30,80] #你开始数一下一共给了多少钱给你 s=sum(getMoney) #打印钱数 print(s) |
以上程序在高级语言中的数据结构很简单
1.将数据存到数组中
2.进行求和存到一个变量中
那计算机中操作怎样将数据存到内存并运算的了,数据在内存中怎样保存的了?
我们现在一步步来,首先我将如上步骤翻译成汇编语言如下(看不懂汇编没关系,后面再说这个数据的结构的原理和特性):
; 运行在x86上的汇编环境 .386 .model flat,stdcall .stack 4096 ExitProcess PROTO, dwExitCode:dword
.data getMoney DWORD 32h,7h,14h,1Eh,50h s DWORD ?
.code main proc
mov ecx,LENGTHOF getMoney ; 数组的中元素个数用于循环中断 mov eax,0 ; 初始化总和0 L1: ; 开始循环 add eax,[edi] ; 放入寄存器,cup加法器进行累加操作 add edi,TYPE getMoney ; 指针移动一个这个数据类型的字节 loop L1 ; ECX = 0 时这个循环结束 mov s,eax ; 将cpu中寄存器的值写入到s内存中 invoke ExitProcess,0 main endp end main |
这里的汇编语言是直接运行在intel x86环境(64位不容易观看)我们直接用vs2015打开(在校企的的那段时间学的是C#,但是这个工具编写汇编也是很友好和强大的),现在一步步讲解那段代码的一个运行过程。
汇编运行过程是:汇编语言-编译成机器语言(即0-1用来驱动计算机电子元件)-通过链接器-cpu执行这段程序。
大家可以看到首先,我们的程序会向CPU发送指令(不同的计算机厂商,会有不同的内存指令操作)申请一段内存,这段内存段没有程序使用,并是空闲的,并将数据写入到内存中。
这里用的是16进制表示法,实际在计算机硬件中是二进制高低电平表示,但是一般我们书写表示方法都习惯用16位进制表示。
所以我们需要知道数组大小,和这个数据每个所占用的字节(所以一般高级语言显示或者隐式的声明这个数据类型,就是想知道这个数据在内存中占用多少字节)用于循环累加,这里的累加使用的是硬件上的加法器如下格式:
我们可以看到如下图中执行的过程
很明显最后CPU加法器运算出来的结果和我们在python中输出的结果是一致的:
以下是我们常见的数据结构:
我们可以举一个数据结构影响效率的例子。
如下:
同样的字符串相加的操作前者比后者慢了上百倍,导致这个的原因是因为字符串的数据结构是堆栈,而字符生成器使用的数据结构是链表,这样说可能很抽象,我这边画一个图形就好理解了。
第一个使用字符相加的时候,每次相加就重新申请一个可以容纳该字符加上已有字符的内存空间:
从效率上将第二个是非常高的。
除了数据结构外,算法(实际上算法就是解决问题明确而有限的步骤,不要想的有多高大上)也在程序中对效率影响很高,这里我直接用python举一个例子(这个例子是1+2+3…+100000 算出结果):
import numpy as np import time sum=0 i=100000 s_k=time.time() while i>0: #n*c1 sum=sum+i #n*c2 i = i - 1 # n*c3 print(time.time()-s_k) print(sum) s_k=time.time() sum=(1+100000)*100000/2 #1*c1 print(time.time()-s_k) print(sum) |
如上程序我们严格按照一般算法RAM模型指令代价
第一个累积函数执行的这几条语句所需的指令代价为:
S1=n*c1+n*c2+n*c3 (这里的n=1000,c1、c2、c3为每条语句执行的代价常量---计算机使用时钟震荡一般是固定的,我们这里不考虑内存访问层次需要的时间)
提取公因式
S1=n(c1+c2+c3) 很明显消耗时间是线性的。
第二个相加之和执行语句所需要的代价为:
S2=c1
从该模型理论上来讲S2耗时应该来说是非常短的,我们实际运行一下:
那算法和数据结构又怎样联系了,事实上我们知道qq空间中的评论这种数据像一颗树如下:
我们常规的数据库是关系型数据库,这样存放评论信息也可以做到评论与评论和回复之间相关联。
但是我们要进行用户相关性计算的时候,除了考虑相似度算法,还需要考虑合理的数据结构,这样用于分层或者别的计算时,算法可以不仅可以节省指令运算的时间,同时取数据,存数据的时间或者空间也大大节省,这样程序在性能上会有飞速的提升。
所以以上回答了所有问题,接下来写的文章大多是与数据结构和算法相关的,这样不仅仅对自己深入理解,也可以和大家讨论。
以上是关于数据结构与算法原理基本关系和原理的主要内容,如果未能解决你的问题,请参考以下文章