链表

反序链表

删除回忆录丶 提交于 2020-03-05 08:15:22
两次遍历,一次存,一次拼接 public ListNode reverseList(ListNode head) { if(head==null){ return null; } List<ListNode> list = new ArrayList<ListNode>(); //1.遍历链表 ListNode p = head; while(p!=null){ //2.保存每一次遍历的结果 list.add(p); p=p.next; } ListNode r_head=null; //3.从List中取出链表并拼接 for(int i=0;i<list.size();i++){ ListNode n = list.get(i); //逆序凭借链表 n.next = r_head; r_head=n; } return r_head; } 递归 public ListNode reverseList(ListNode head) { if(head==null){ return null; } //终止条件:该节点是最后一个节点 if(head.next==null){ return head; } //求解子问题 ListNode p = reverseList(head.next); //将该节点拼在最后,完成逆序 head.next.next = head; head

链表基础操作

别说谁变了你拦得住时间么 提交于 2020-03-05 06:16:29
链表的操作,包括创建,查找,插入,删除。 1 struct node{ 2 int data; 3 node* next; 4 }; 5 6 void createList(node* head,int var) 7 { 8 node* current_node = head; 9 node* next_node = new node(); 10 next_node->data = var; 11 next_node->next = NULL; 12 while(current_node->next!=NULL){ 13 current_node = current_node->next; 14 } 15 current_node->next = next_node; 16 } 17 18 void ergodicList(node* head) 19 { 20 node* current_node = head; 21 while(current_node->next!=NULL) 22 { 23 current_node = current_node->next; 24 printf("current node's value is %d\n",current_node->data); 25 } 26 } 27 28 void searchElementInList(node*

【JDK】JDK源码分析-HashMap(1)

偶尔善良 提交于 2020-03-05 04:21:10
概述 HashMap 是 Java 开发中最常用的容器类之一,也是面试的常客。它其实就是前文「 数据结构与算法笔记(二) 」中「散列表」的实现,处理散列冲突用的是“链表法”,并且在 JDK 1.8 做了优化,当链表长度达到一定数量时会把链表转为红黑树。 因此,JDK 1.8 中的 HashMap 实现可以理解为「数组 + 链表 + 红黑树」。内部结构示意图: HashMap 的继承结构和类签名如下: public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {} PS: 还记得以前初读 HashMap 源码时,用了周末两天的时间,而且读完脑子里还是一头雾水。当时也没做什么笔记,这次记录一下。 代码分析 一些成员变量 // 默认初始化容量(必须是 2 的次幂) static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 // 最大容量(必须是 2 的次幂,且小于等于 2^30) static final int MAXIMUM_CAPACITY = 1 << 30; // 默认负载因子 static final float DEFAULT_LOAD_FACTOR = 0.75f; //

哈希表

为君一笑 提交于 2020-03-05 00:38:36
一、介绍 哈希表是根据关键字(Key)而 直接访问记录 的数据结构。它通过把 关键字 映射到哈希表中的 一个位置 来访问 记录 ,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做哈希表。 散列函数:将记录的关键字映射到该记录在哈希表中的存储位置,即 f(关键字) = 记录的存储位置 示例:以查新华字典为例,假设我们要查看“猪”的详细信息,我们一般会根据拼音“zhu”去查找拼音索引,通过拼音索引我们得到了“zhu”在字典中的页码数。其中, 拼音索引就是 散列函数 ,“zhu”就是 关键字 ,查到的页码值就是 哈希值 ,而“猪”的详细信息则是我们所 要访问的记录 。 二、哈希冲突 哈希冲突:当key1≠key2时,却有f(key1) = f(key2) 。 三、拉链法 当发生哈希冲突时,我们通过两个不同的关键字,将访问到同一个记录。既然它们在哈希表中的存储位置相同,那我们可以在该位置 引出一个链表 ,将所有根据散列函数定位到该存储位置的记录都插入到该链表上。 这是哈希表最常用的一种实现方法,可以理解为“链表的数组”,其具有以下优点:   a.寻址容易(数组的特点)   b.插入和删除容易(链表的特点) 所以查找、插入、删除(有时包括删除)可以达到O(1)。 示例:现有一堆数据{1, 12, 26, 337, 353...},散列函数是H(key)=key mod 16

python 剑指offer(一)从尾到头打印链表

烂漫一生 提交于 2020-03-05 00:12:16
链表的定义 链表的定义:是一组数据项的集合,其中每个数据项都是一个节点的一部分,每个节点还包含指向下一个节点的链接 链表的结构:data为自定义的数据,next为下一个节点的地址。 基本元素 : 节点:每个节点有两个部分,左边称为值域,存放用户数据;右边部分称为指针域,用来存放指向下一个元素的指针。 head:head节点永远指向第一个节点 tail: tail永远指向最后一个节点 None:链表中最后一个节点的指针域为None值 题目 输入一个链表,按链表从尾到头的顺序返回一个ArrayList class Solution: # 返回从尾部到头部的列表值序列,例如[1,2,3] def printListFromTailToHead(self, listNode): # write code here s = list() while listNode: s.append(listNode.val) listNode = listNode.next return s[::-1] # s.reverse() 来源: CSDN 作者: 小菜菜1223 链接: https://blog.csdn.net/qq_40771567/article/details/104649101

线性表和链表

佐手、 提交于 2020-03-04 23:33:14
线性表的定义: (List) typedef int position; typedef struct LNode* PtrToNode; typedef PtrToNode List; struct LNode{//数据从data[0]开始,last记录线性表中最后一个元素在表中的位置,表长为last+1; int date[maxsize]; position last;//表空时,last = -1; }; 以下是顺序表的主要操作以及实现: 1.初始化(构造一个空表) List MakeEmpty() { List L; L = (List)malloc(sizeof(struct LNode)); L->last = -1;//表示表空 return L; } 2.查找:在线性表中,查找与给定值x相等的数据元素。查找成功就返回X在线性表中的下标,否则返回错误信息error #define error -1 position Find(List L, int x) { position i =0;//i记录下标,从0开始 while(i<=L->Last && L->date[i]!=x) i++; //跳出while时说明:要么i>last,要么x=date[i] if(i>L->Last)//检查i是否越界 return error; else return i; } 3

用链表实现栈

独自空忆成欢 提交于 2020-03-04 22:15:42
链表实现栈的实例图如下: 压栈(入栈) 弹栈(出栈) 完整代码如下: # include <iostream> # include <Windows.h> using namespace std ; typedef int ElemType ; //数据类型取别名,方便代码后期维护和修改 typedef struct _Sqinn { ElemType data ; //节点数据域 _Sqinn * next ; //节点指针域 } Sqinn , * Linkinn ; typedef struct _Sqinnret { Linkinn top ; //栈顶 int cout ; //栈的元素个数 } Sqinnret ; //初始化 bool InitSqinn ( Sqinnret * & s ) { if ( ! s ) return false ; s = new Sqinnret ; s - > top = NULL ; s - > cout = 0 ; return true ; } /* 入栈 首先创建一个节点,把插入的数据放进去, 在让栈顶指针指向他,最后cout++ */ bool SqinnInsert ( Sqinnret * & s , ElemType & e ) { if ( ! s ) return false ; Sqinn * node = (

Redis(2)——跳跃表

亡梦爱人 提交于 2020-03-04 22:14:26
一、跳跃表简介 跳跃表(skiplist)是一种随机化的数据结构,由 William Pugh 在论文《Skip lists: a probabilistic alternative to balanced trees》中提出,是一种可以与平衡树媲美的层次化链表结构——查找、删除、添加等操作都可以在对数期望时间下完成,以下是一个典型的跳跃表例子: 我们在上一篇中提到了 Redis 的五种基本结构中,有一个叫做 有序列表 zset 的数据结构,它类似于 Java 中的 SortedSet 和 HashMap 的结合体,一方面它是一个 set 保证了内部 value 的唯一性,另一方面又可以给每个 value 赋予一个排序的权重值 score,来达到 排序 的目的。 它的内部实现就依赖了一种叫做 「跳跃列表」 的数据结构。 为什么使用跳跃表 首先,因为 zset 要支持随机的插入和删除,所以它 不宜使用数组来实现,关于排序问题,我们也很容易就想到 红黑树/ 平衡树 这样的树形结构,为什么 Redis 不使用这样一些结构呢? 性能考虑: 在高并发的情况下,树形结构需要执行一些类似于 rebalance 这样的可能涉及整棵树的操作,相对来说跳跃表的变化只涉及局部 (下面详细说); 实现考虑: 在复杂度与红黑树相同的情况下,跳跃表实现起来更简单,看起来也更加直观; 基于以上的一些考虑

21.合并两个有序链表

只谈情不闲聊 提交于 2020-03-04 19:49:48
无比丑陋的代码: /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public : ListNode * mergeTwoLists ( ListNode * l1 , ListNode * l2 ) { if ( ! l1 ) return l2 ; if ( ! l2 ) return l1 ; auto l3 = l1 ; auto l4 = l2 ; if ( l1 - > val > l2 - > val ) //保证ll是小的 { l1 = l2 ; l2 = l3 ; } auto res = l1 ; while ( l1 - > next && l2 ) { if ( l1 - > next - > val <= l2 - > val ) l1 = l1 - > next ; else { //画图比较清楚 l4 = l2 - > next ; //保存l2下一个数 l3 = l1 - > next ; //保存l1下一个数 l1 - > next = l2 ; //拼接 l1 = l1 - >

剑指offer:合并两个有序链表

扶醉桌前 提交于 2020-03-04 19:47:44
题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 解题思路 一、非递归 ①利用两个node(head、cur),head指向头节点,cur指向当前处理的节点。 ②遍历比较list1和list2的元素,将小的元素添加入链表,如果一条链表遍历结束,将另一条剩余元素合并到新链表。 ③最后返回头节点。 public ListNode Merge(ListNode list1,ListNode list2) { if(list1 == null){ //list1为空 return list2; } if(list2 == null){ //list2为空 return list1; } ListNode head = null; ListNode cur = null; while(list1 != null && list2 != null){ //当list1 与 list2 都不为空 if(list1.val < list2.val){ //list1的元素 小于 list2的元素 if(head == null){ //当添加第一个元素 cur = head = list1; //头节点指向第一个元素 }else{ cur.next = list1; //将元素添加入链表 cur = cur.next; //移动cur指针 }