指针

B树和B+树

佐手、 提交于 2020-01-08 06:36:09
B树 一、 基本原理   B树是一种查找树,它最初启发于二叉查找树。   二叉查找树的特点是每个非叶节点都只有两个孩子节点。然而这种做法会导致当数据量非常大时,二叉查找树的深度过深,搜索算法自根节点向下搜索时,需要访问的节点也就变的相当多。   如果这些节点存储在外存储器中,每访问一个节点,相当于就是进行了一次I/O操作,随着树高度的增加,频繁的I/O操作一定会降低查询的效率。 磁盘读取信息:   找到存储这个数据所对应的磁盘页面,这个过程是机械化的过程,需要依靠磁臂的转动,找到对应磁道,所以耗时长。   读取数据进内存,并实施运算,这是电子化的过程,相当快。   对于外存储器的信息读取最大的时间消耗在于寻找磁盘页面。那么一个基本的想法就是能不能减少这种读取的次数,在一个磁盘页面上,多存储一些索引信息。   B树的基本逻辑就是这个思路,它要改二叉为多叉,每个节点存储更多的指针信息,以降低I/O操作数。 二、基本结构 1. B树的定义 这里用最小度 t 来定义B树。一棵最小度为 t 的B树是满足如下四个条件的平衡多叉树: 每个节点最多包含 2 t − 1 个关键字;除根节点外的每个节点至少有 t − 1 个关键字( t ≤ 2 ),根节点至少有一个关键字; 一个节点 u 中的关键字按非降序排列: u . k e y 1 ≤ u . k e y 2 ≤ … u . k e y n ;

数据结构~链表

南楼画角 提交于 2020-01-08 05:41:05
返回目录 概况 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,链表比较方便插入和删除操作。 链表 (Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表:顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。在计算机科学中,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向明上一个/或下一个节点的位置的链接("links")。链表最明显的好处就是

C语言指针/指向指针的指针

别来无恙 提交于 2020-01-08 04:36:12
先看一段代码: 1 #include <stdio.h> 2 3 int main () 4 { 5 int i = 30; 6 int* pi; 7 int** ppi; 8 9 pi = &i;10 ppi = π11 12 printf("i = %d;\t &i = %d\n", i, &i);13 printf("pi = %d;\t &pi = %d;\t *pi = %d\n", pi, &pi, *pi);14 printf("ppi = %d;\t *ppi = %d;\t &ppi = %d;\t **ppi = %d\n", \15 ppi, *ppi, &ppi, **ppi);16 17 return 0;18 } 执行结果: i = 30; &i = -1013781316 pi = -1013781316; &pi = -1013781328; *pi = 30 ppi = -1013781328; *ppi = -1013781316; &ppi = -1013781336; **ppi = 30 下面用一个简单的图来说明一下: 定义指针类型时,用下面的格式,感觉更容易理解: int *p;    =>   int* p; int **pp;   =>   int** pp; =>右边的写法可以更加明确的看出int*, int**是变量类型,p,

C语言中的强制类型转换

纵然是瞬间 提交于 2020-01-08 04:18:42
C语言中,任何一个变量都必须占有一个地址,而这个地址空间内的0-1代码就是这个变量的值。不同的数据类型占有的空间大小不一,但是他们都必须有个地址,而这个地址就是硬件访问的依据,而名字只是提供给程序员的一种记住这个地址的方便一点的方法。但是,不同的变量在机器中都是0-1代码,所以,我们不能简单的通过检查一个值的位来判断它的类型。 例如,定义如下: int a; float b; double c; long double d; ( 假设它们所占的字节分别是 4 、 8 、 8 、 10 ,而且连续存储于某个地址空间,起始地址是 100 ,则我们可以得到如下内存分布 ) a变量就是由以地址100开始到103结束的4个字节内存空间内的0-1代码组成。b变量则是由以地址104开始到112结束的8个字节内存空间内的0-1代码组成。而在机器中,这些内存都是连续的0-1代码,机器并不知道100~103是整型而104~111是float型,所有这些类型都是编译器告知的。当我们用a时,由于前面把a定义为int型,则编译器知道从a的地址开始向后取4个字节再把它解释成int型。那么(float)a,就是先按照int类型取出该数值,再将该数值按照int to float的规则转换成float型。所以强制类型转换就是按照某个变量的类型取出该变量的值,再按照***to***的规则进行强制转转换。如果是(类型名

数据结构与算法练习---环形队列代码

北慕城南 提交于 2020-01-08 02:11:50
用数组来实现一个环形队列,关键在于找出判断队列是空还是满状态的条件和利用头指针front和尾指针rear来计算有效元素个数的公式。 设置front为头指针指向第一个元素,初始值为0. 设置rear为尾指针指向最后一个元素的后一个位置,初始值为0. maxSize为用来形成环形队列的数组的大小。 队列已满的条件:(rear + 1) % maxSize == front 队列为空的条件:rear == front 队列中有效元素的个数为: (rear + maxSize -front) % maxSize 代码如下: ```java package arrQueueDemo; import java.util.Scanner; public class CircleArrayQueue { //main方法用来测试环形队列 public static void main(String[] args) { //创建数组队列对象 CycArrayQueue arrQueue = new CycArrayQueue(4); char key = ' '; Scanner sc = new Scanner(System.in); boolean loop = true; while(loop) { System.out.println("输入a(add),向队列中添加数据!");

C语言指针类型 强制转换

坚强是说给别人听的谎言 提交于 2020-01-08 01:50:40
关于C语言指针类型 强制转换 引用一篇文章: C语言中,任何一个变量都必须占有一个地址,而这个地址空间内的0-1代码就是这个变量的值。不同的数据类型占有的空间大小不一,但是他们都必须有个地址,而这个地址就是硬件访问的依据,而名字只是提供给程序员的一种记住这个地址的方便一点的方法。但是,不同的变量在机器中都是0-1代码,所以,我们不能简单的通过检查一个值的位来判断它的类型。 例如,定义如下: int a; float b; double c; long double d; (假设它们所占的字节分别是 4、 8、 8、 10,而且连续存储于某个地址空间,起始地址是 100,则我们可以得到如下内存分布 ) a变量就是由以地址100开始到103结束的4个字节内存空间内的0-1代码组成。b变量则是由以地址104开始到112结束的8个字节内存空间内的0-1代码组成。而在机器中,这些内存都是连续的0-1代码,机器并不知道100~103是整型而104~111是float型,所有这些类型都是编译器告知的。当我们用a时,由于前面把a定义为int型,则编译器知道从a的地址开始向后取4个字节再把它解释成int型。那么(float)a,就是先按照int类型取出该数值,再将该数值按照int to float的规则转换成float型。所以强制类型转换就是按照某个变量的类型取出该变量的值,再按照***to**

go语言之行--结构体(struct)详解、链表

情到浓时终转凉″ 提交于 2020-01-08 00:55:33
一、struct简介 go语言中没有像类的概念,但是可以通过结构体struct实现oop(面向对象编程)。struct的成员(也叫属性或字段)可以是任何类型,如普通类型、复合类型、函数、map、interface、struct等,所以我们可以理解为go语言中的“类”。 二、struct详解 struct定义 在定义struct成员时候区分大小写,若首字母大写则该成员为公有成员(对外可见),否则是私有成员(对外不可见)。 type struct_variable_type struct { member member_type member member_type ..... member member_type } //示例 type Student struct { name string age int Class string } 声明与初始化 var stu1 Student var stu2 *Student= &Student{} //简写stu2 := &Student{} var stu3 *Student = new(Student) //简写stu3 := new(Student) struct使用 在struct中,无论使用的是指针的方式声明还是普通方式,访问其成员都使用".",在访问的时候编译器会自动把 stu2.name 转为 (*stu2).name。

码农找工作之:秒杀算法面试必须掌握的14种模式

ぃ、小莉子 提交于 2020-01-07 20:38:40
对于茫茫多的程序员来说,准备算法面试简直就是一个亚历山大的过程。看不完的学习资料,更惨的是,很多内容和程序员干的事情感觉相去甚远,这无疑只会雪上加霜。 这样的结果之一就是:程序员需要花上数周的时间在诸如LeetCode这样的在线编程平台上准备刷上几百个面试题目。这些焦虑的程序员都关心类似的问题: 我刷了足够的题了吗?我应该再来点吗? 这就是为啥我专注于帮助码农们掌握每个问题背后的模式的原因:这样的话,你们就不需要苦逼哈哈地担心着茫茫多的(一千多道)LeetCode的进度条了,也帮助你们避免盲目刷题的疲劳。如果你理解这些通用的模式,你就可以把他们当做是模板,去解决其他类似的被改头换面过的题目了。 这篇文章就和大家唠唠所有的面试题目可能的14种模式。当然更重要的,我会给大家讲讲怎么去识别每种模式,每个模式再给大家来几个样题尝尝鲜。当然,这些只是冰山一角啦,详细的,不用多说,墙裂推荐你去看这门课: Grokking the Coding Interview: Patterns for Coding Questions 该课程提供详细的理论讲解,例子和编程训练。 如果你需要买该网址的任何课程,都可以使用coupon code: awesome-developer-20 拿到额外八折。 接下来的这些模式是建立在你已经知晓了数据结构的基础之上的。如果你还没掌握的话,嘿嘿,推荐你去看:

「每日五分钟,玩转JVM」:指针压缩

落爺英雄遲暮 提交于 2020-01-07 18:56:34
64位JVM和32位JVM 最初的时候,JVM是32位的,但是随着64位系统的兴起,JVM也迎来了从32位到64位的转换,32位的JVM对比64位的内存容量比较有限,但是我们使用64位虚拟机的同时,也带来了一个问题,64位下的JVM中的对象会比32位中的对象多占用1.5倍的内存空间,这是我们不想看到的(又要马儿跑,又要马儿不吃草可还行?),但是机智的程序员不会屈服,所以在JDK 1.6的版本后,我们在64位中的JVM中可以开启指针压缩(UseCompressedOops)来压缩我们对象指针的大小来帮助我们节约内存空间,拿JDK 8来说,这个指令是默认开启的。 如果我想要知道我们电脑上安装的JVM是32位的还是64位的,可以通过下面的这个命令去查看 如果我们的系统是64位的,当我们输入 java -d32 的时候会提示不支持32位的JVM,或者我们通过 java -version 也可以看到: image-20190911201937600 指针压缩 当我们启用了 -XX:+UseCompressedOops 之后,我们原本的OOP(Ordinary Object Pointer,普通对象指针)就会被压缩,当然也不是所有的对象都会被压缩,只有 以下几种的对象才会被压缩 对象的 全局静态变量 (类属性) 对象头信息 对象的引用类型 对象数组类型 而以下几种对象则不能被压缩:

[go]内存对齐

余生长醉 提交于 2020-01-07 18:29:31
参考 参考-校对版 理解类型的本质 当我使用 C/C++ 编写代码时,理解类型(type)是非常有必要的。如果不理解类型,你就会在编译或者运行代码的时候,碰到一大堆麻烦。无论什么语言,类型都涉及到了编程语法的方方面面。 加强对于类型和指针的理解,对于提高编程水平十分关键。 本文会主要讲解类型。 我们首先来看看这几个字节的内存: 内存地址: FFE4 FFE3 FFE2 FFE1 存储的值: 00000000 11001011 01100101 00001010 请问地址 FFE1 上字节的值是多少? 如果你试图回答一个结果,那就是错的。为什么?因为我还没有告诉你这个字节表示什么。(不同类型的含义不同) 回答 10,那么你又错了。为什么?因为当我说这是数字的时候,你认为我是指十进制的数字。 基数(number base): 所有编号系统(numbering system)要发挥作用,都要有一个基(base)。 从你出生的时候开始,人们就教你用基数 10 来数数了。 这可能是因为我们大多数人都有 10 个手指和 10 个脚趾。另外,用基数 10 来进行数学计算也很自然。 基定义了编号系统所包含的符号数。基数 10 会有 10 个不同的符号,用以表示我们可以计量的无限事物。 基数 10 的编号系统为 0、1、2、3、4、5、6、7、8、9。一旦超过了 9,我们需要增加数的长度。 例如