什么叫数据结构:
个人认为,数据结构就是现实版的一个存储架构,好比我们现实世界,钱存在银行,水装在容器里,书本放在书架上,不同的事物总要找到一个适合存放的地方。
万物皆为程序,万物皆需存储,然而包装成什么结构进行存储,是一门学问。就好比钱放到一个塑料袋里存储好,还是放到钱包分类存储好,如果我们把线性结构
比作塑料袋,把二叉树比作钱包,数据就是money,最终他们存在内存储器(银行)。。。乱扯的
那么电脑里面的数据应该如何存放呢,无非就是一串的二进制如何存在计算机里面,
首先得先来了解一下计算机的硬件:
1.寄存器
是中央处理器内的组成部份。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,包含的寄存器有累加器(ACC)。
寄存器是CPU内部的元件,寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。
寄存器是CPU里的东西,内存是挂在CPU外面的数据总线上的,访问内存时要在CPU的寄存器填上地址,再执行相应的汇编指令,这时CPU会在数据总线上生成读取或写入内存数据的时钟信号,最终内存的内容会被CPU寄存器的内容更新(写入)或被读入CPU的寄存器(读取),不只是PC上的CPU,所有的嵌入式CPU,单片机都一个样,
这样就可以回忆起大学时代学的汇编,一条条的指令,操作着cpu里面的寄存器,后面人类受不了这种麻烦的操作,而且不直观,才会出现c,c++,然后指针就负责操纵这些寄存器,就是普遍说的指针
指向地址,寄存器地址,寄存器里存放了数据。后面人类又受不了指针,才出现了java,都是引用没有指针,语言层面只会越来越简单,容易上手,不必过于关注底层,只管上层应用,后面lua,python
各种各样语言层出不穷,以后可能c/c++会被淘汰了,就像汇编那样越来越少人去关注了,扯远了。。。
int i = 5 仅仅是定义了一个4个字节(int)的变量i。(内存地址)
int &k = i 将i放入寄存器 k里面。(寄存器)
可以亲自验证下,以下是vs2013编辑器debug时的反汇编代码,eax就是寄存器,
int p2 = 123;
0131AC8E mov dword ptr [p2],7Bh
int &p3 = p2;
0131AC98 lea eax,[p2]
0131AC9E mov dword ptr [p3],eax
int *p1 = &p2;
0131ACA4 lea eax,[p2]
0131ACAA mov dword ptr [p1],eax
可以看看寄存器的寻址方式:
http://wenku.baidu.com/link?url=jBYQdGUDBsUw7p8fvDSlrUfIEquE_lLoYK_PdTeHjmXtPd_FblFfUS_dzhbncsWkitGckI1oBT9YKgsLl8aQBAMjVTHVWLjhKmmKUamGpZS
2. 内存包含的范围非常广,一般分为只读存储器(ROM)、随机存储器(RAM)和高速缓存存储器(cache)。
大致来说数据是通过内存-Cache-寄存器,Cache缓存则是为了弥补CPU与内存之间运算速度的差异而设置的的部件。
内存寻址 首先,内存从CPU获得查找某个数据的指令,然后再找出存取资料的位置时(这个动作称为“寻址”)
总得来说:
堆栈是内存中的一个数据结构.
内存是CPU和硬盘之间的通道.
寄存器是CPU的存储器,速度快.
好了,基本的说完,下面转为正题:
堆和栈,永恒的比较,
个人认为:堆在内存里,动态分配内存,语言库给它的一个概念;栈在寄存器里,栈机器系统提供的数据结构,分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。
栈是一块连续的内存的区域,一级缓存。
堆是向高地址扩展的数据结构,是不连续的内存区域,二级缓存。
void f()
{
int* p=new int[5];
}
这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的
指针p.在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中。
所以说基本的数据类型int float 还有指针这些都是栈为其分配了空间,直接操作寄存器。
这哥们的blog已经写得很详细很清楚了,还有static机制:
http://blog.youkuaiyun.com/chenxiancool/article/details/6899235
队列和栈刚好相反,栈是后进先出,队列是先进先出。
队列和栈都是线性表,数据元素之间存在“一对一”的关系。
线性表说完,接下来再说说树和哈希表,差不多了,后面就是一些链表,数组,哈希算法...
树主要是一些二叉树,平衡二叉树,红黑树;链表主要是单链表,双链表,循环链表;哈希表主要是哈希算法,如何解决哈希冲突。
平衡二叉树:AVL是一种高度平衡的二叉树,它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树所以通常的结果是,维护这种高度平衡所付出的
代价比从中获得的效率收益还大,故而实际的应用不多,更多的地方是用追求局部而不是非常严格整体平衡的红黑树。
当然,如果场景中对插入删除不频繁,只是对查找特别有要求,AVL还是优于红黑的。
红黑树:通过对任何一条从根到叶子的简单路径上各个节点的颜色进行约束,确保没有一条路径会比其他路径长2倍,因而是近似平衡的。
所以相对于严格要求平衡的AVL树来说,
它的旋转保持平衡次数较少。
用于搜索时,插入删除次数多的情况下我们就用红黑树来取代AVL。
性质1. 节点是红色或黑色。
性质2. 根节点是黑色。
性质3 每个叶节点(NIL节点,空节点)是黑色的。
性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
时间复杂度为O(logn)