链表

Redis Hash哈希(2)

断了今生、忘了曾经 提交于 2020-03-12 01:54:58
存储类型 包含键值对的无序散列表。value只能是字符串,不能嵌套其他类型。 同样是存储字符串,Hash与String的主要区别? 1、把所有相关的值聚集到一个key中,节省内存空间 2、只使用一个key,减少key冲突 3、当需要批量获取值的时候,只需要使用一个命令,减少内存/IO/CPU的消耗 Hash不适合的场景: 1、Field不能单独设置过期时间 2、没有bit操作 3、需要考虑数据量分布的问题(value值非常大的时候,无法分布到多个节点) 存储(实现)原理 Redis的Hash本身也是一个KV的结构,类似于Java中的HashMap。 外层的哈希(RedisKV的实现)只用到了hashtable。当存储hash数据类型时,我们把它叫做内层的哈希。内层的哈希底层可以使用两种数据结构实现: ziplist:OBJ_ENCODING_ZIPLIST(压缩列表) hashtable:OBJ_ENCODING_HT(哈希表) 执行命令 ziplist压缩列表 ziplist是一个经过特殊编码的双向链表,它不存储指向上一个链表节点和指向下一个链表节点的指针,而是存储上一个节点长度和当前节点长度,通过牺牲部分读写性能,来换取高效的内存空间利用率,是一种时间换空间的思想。只用在字段个数少,字段值小的场景里面。 ziplist的内部结构 ziplist.c源码第16行的注释:

js数据结构与算法存储结构

孤街醉人 提交于 2020-03-12 01:50:30
数据结构(程序设计=数据结构+算法) 数据结构就是关系,没错,就是数据元素相互之间存在的一种或多种特定关系的集合。 传统上,我们把数据结构分为逻辑结构和物理结构。 逻辑结构: 是指数据对象中数据元素之间的相互关系,也是我们今后最需要关注和讨论的问题。 物理结构: 是指数据的逻辑结构在计算机中的存储形式。 常用的数据结构有: 数组,队列(queue),堆(heap),栈(stack),链表(linked list ),树(tree),图(graph)和散列表(hash) 栈(stack):运算只在表的一端进行;队列(Queue):运算只在表的两端进行。 队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。 与栈相反,队列是一种先进先出(First In First Out, FIFO)的线性表。 与栈相同的是,队列也是一种重要的线性结构,实现一个队列同样需要顺序表或链表作为基础。 四大结构 集合结构 线性结构 树形结构 图形结构 顺序存储和链式存储 数据元素的存储结构形式有两种:顺序存储和链式存储。 例如我们编程语言的数组结构就是这样滴。 链式存储结构:是把数据元素存放在任意的存储单元里,这组存储单元可以是连续的,也可以是不连续的。 链式存储结构 线性表 线性表:就好像是排队一样,具有线一样性质的结构,它是由零个或多个数据元素组成的有限序列。 若元素存在多个

HashMap详解

爷,独闯天下 提交于 2020-03-11 19:26:50
hashmap的数据结构 Hashmap的底层数据结构是由数组+链表组成的,是线程不安全,允许key和value为null。底层结构数组叫哈希桶,而桶内则是链表,链表中的节点Node存放着实际的元素。 JDK 1.8 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也很难达到元素百分百均匀分布。 当 HashMap 中有大量的元素都存放到同一个桶中时,这个桶下有一条长长的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复杂度就是 O(n),完全失去了它的优势。 针对这种情况,JDK 1.8 中引入了 红黑树(查找时间复杂度为 O(logn))来优化这个问题。 新增的操作:桶的树形化 treeifyBin() 新增的操作: 红黑树中添加元素 putTreeVal() 新增的操作: 红黑树中查找元素 getTreeNode() 新增的操作: 树形结构修剪 split() JDK 1.8 以后哈希表的 添加、删除、查找、扩容方法都增加了一种 节点为 TreeNode 的情况: 添加时,当桶中链表个数超过 8 时会转换成红黑树; 删除、扩容时,如果桶中结构为红黑树,并且树中元素个数太少的话,会进行修剪或者直接还原成链表结构; 查找时即使哈希函数不优,大量元素集中在一个桶中,由于有红黑树结构,性能也不会差。 (图片来自:http:/

leetcode系列-相交链表(看到这个题解,我都惊呆了系列)

a 夏天 提交于 2020-03-11 17:15:56
分类:链表 难度:easy 方法:双指针 相交链表 编写一个程序,找到两个单链表相交的起始节点。 如下面的两个链表: 在节点 c1 开始相交。 示例 1: 输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 输出:Reference of the node with value = 8 输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。 示例 2: 输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 输出:Reference of the node with value = 2 输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。 示例 3: 输入:intersectVal = 0,

Java用链表实现堆栈

荒凉一梦 提交于 2020-03-11 17:10:00
定义 一种线性的存储结构,实现先进后出的原则,用链表实现的时候只能从头节点开始才能实现完整的铺上,pop,peap的完整操作,不同于数组的实现,链表不需要判断栈不否满了,只需要判断是否为空。 入栈:在头指针后面插入数据; 出栈:把头指针后一位的数据输出; 链表的定义 package com.jiedada.jiegou; public class Node1 { private Object data; private Node1 next; public Node1() { this.data=null; this.next=null; } public Node1(Object data) { this.data=data; this.next=null; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public Node1 getNext() { return next; } public void setNext(Node1 next) { this.next = next; } } View Code 链表的实现方法 package com.jiedada.jiegou; public class Link { Node1

C语言描述链表的实现及操作

点点圈 提交于 2020-03-11 17:05:39
一.链表的创建操作 // 操作系统 win 8.1 // 编译环境 Visual Stuido 2017 #include<stdio.h> #include<malloc.h> #include<stdlib.h> typedef int ElementType; // 定义数据类型,可根据需要进行其他类型定义 // 链表节点的定义 typedef struct ListNode { ElementType Element; // 数据域,存放数据 ListNode* Next; // 指向下一个链表节点 }Node, *PNode; // 链表创建函数定义 PNode CreateList(void) { int len ; // 用于定义链表长度 int val ; // 用于存放节点数值 PNode PHead = (PNode)malloc(sizeof(Node)); // 创建分配一个头节点内存空间//头节点相当于链表的哨兵,不存放数据,指向首节点(第一个节点) if (PHead == NULL) // 判断是否分配成功 { printf("空间分配失败 \n"); exit(-1); } PNode PTail = PHead; // 链表的末尾节点,初始指向头节点 PTail->Next = NULL; // 最后一个节点指针置为空 printf(

237:删除链表中的节点

血红的双手。 提交于 2020-03-11 13:09:05
问题描述 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。 现有一个链表 – head = [4,5,1,9],它可以表示为: 示例 输入 : head = [ 4 , 5 , 1 , 9 ] , node = 5 输出 : [ 4 , 1 , 9 ] 解释 : 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 - > 1 - > 9. 输入 : head = [ 4 , 5 , 1 , 9 ] , node = 1 输出 : [ 4 , 5 , 9 ] 解释 : 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 - > 5 - > 9. 说明: 链表至少包含两个节点。 链表中所有节点的值都是唯一的。 给定的节点为非末尾节点并且一定是链表中的一个有效节点。 不要从你的函数中返回任何结果。 问题分析 这题是真坑。一直都Head,head的。我一直以为S端给定义了head。就按照常规的删除来写的。 编译不过。嗯,可见人家并没有给head.只给了个node。 那咋整呢? 我们可以把node的下一个结点的值给抓过来,相当于是直接抹除了node的值。然后node的下一个结点就没有利用价值了,跳过他即可。 解决方案 class Solution { public void deleteNode

双链表

青春壹個敷衍的年華 提交于 2020-03-11 10:49:43
定义:每个数据结点都有两个指针,分别指向直接后继和直接前驱,结构特点如下 双链表结构 指针域 数据域 指针域 prior data next prior data1 next prior data2 next prior data3 next NULL 定义: typedef int Type typedef struct _DListNode{ struct _DListNode *prior; struct _DListNode *next; Type data; void* data1; }DListNode; 各种可能的操作 //操作双链表 static DListNode *create(void); static int find(DListNode *dlist,Type find_data); static DListNode *change(DListNode *dlist,int pos,Type data); static DListNode *insert(DListNode *dlist,Type data,int pos); static DListNode *delete(DListNode *dlist,Type data); static void display(DListNode *list); 创建双链表 static DListNode

02.07、链表相交

泪湿孤枕 提交于 2020-03-11 10:10:59
这道题主要的问题在于两条链表长度不同,而且是按照地址来确定相交点的。我刚开始的想法是将两个链表的值分别扔进vector里,然后倒着遍历,当出现不同时,+1就是相交点。想一想定义一个 vector<ListNode*>这样应该可以 这道题有一个很巧的做法,就是定义头节点,让它们对面条链表都进行遍历,这样就很巧的消除了这两条链表的长度差。 意思就是first先对A链表进行遍历 second先对B进行遍历。当短的那条遍历完后,将它再对长的那条遍历,长的那条遍历完后对短的那条遍历。这样就很巧的消除长度差,两个节点遍历的长度都是两条链表长度和。这样找到交叉点就很简单。 /** Definition for singly-linked list. struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; */ class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { ListNode* first=headA; ListNode* second=headB; while(first!=second) { if(first!= NULL) first=first

相交链表

◇◆丶佛笑我妖孽 提交于 2020-03-11 03:31:56
编写一个程序,找到两个单链表相交的起始节点。 注意: 如果两个链表没有交点,返回 null . 在返回结果后,两个链表仍须保持原有的结构。 可假定整个链表结构中没有循环。 程序尽量满足 O( n ) 时间复杂度,且仅用 O( 1 ) 内存。 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { if(headA == NULL || headB == NULL) return NULL; ListNode *p = headA; ListNode *q = headB; while(p->next != NULL){ p = p->next; } while(q->next != NULL){ q = q->next; } if(p != q){ return NULL; } else{ p = headA; q = headB; while(p != q){ p = p-