链表

HashMap

元气小坏坏 提交于 2020-02-20 05:10:17
https://www.cnblogs.com/aobing/p/12014271.html HashMap是我们非常常用的数据结构,由 数组和链表组合构成 大概如下,数组里面每个地方都存了Key-Value这样的实例,在Java7叫Entry在Java8中叫Node。 因为他本身所有的位置都为null,在put插入的时候会根据key的hash去计算一个index值。 你提到了还有链表,为啥需要链表,链表又是怎么样子的呢? 我们都知道数组长度是有限的,在有限的长度里面我们使用哈希,哈希本身就存在概率性,就是”帅丙“和”丙帅“我们都去hash有一定的概率会一样,就像上面的情况我再次哈希”丙帅“极端情况也会hash到一个值上,那就形成了链表。 每一个节点都会保存自身的hash、key、value、以及下个节点,我看看Node的源码。 来源: https://www.cnblogs.com/ywsheng/p/12016418.html

HashMap-treeifyBin()源码简读(JDK1.8)

拟墨画扇 提交于 2020-02-20 05:03:41
HashMap的treeifyBin()方法源码 final void treeifyBin ( Node < K , V > [ ] tab , int hash ) { //定义几个变量,n是数组长度,index是索引 int n , index ; Node < K , V > e ; //这里的tab指的是本HashMap中的数组,n为数字长度,如果数组为null或者数组长度小于64 if ( tab == null || ( n = tab . length ) < MIN_TREEIFY_CAPACITY ) //则调用resize()方法直接扩容,不转红黑树 resize ( ) ; //否则说明满足转红黑树条件,通过按位与运算取得索引index,并将该索引对应的node节点赋值给e,e不为null时 else if ( ( e = tab [ index = ( n - 1 ) & hash ] ) != null ) { //定义几个变量,hd代表头节点,tl代表尾节点 TreeNode < K , V > hd = null , tl = null ; do { //先把e节点转成TreeNode类型,并赋值给p TreeNode < K , V > p = replacementTreeNode ( e , null ) ; //如果尾节点tl为空

单链表

荒凉一梦 提交于 2020-02-20 03:22:13
实现一个单链表,链表初始为空,支持三种操作: (1) 向链表头插入一个数; (2) 删除第k个插入的数后面的数; (3) 在第k个插入的数后插入一个数 现在要对该链表进行M次操作,进行完所有操作后,从头到尾输出整个链表。 注意:题目中第k个插入的数并不是指当前链表的第k个数。例如操作过程中一共插入了n个数,则按照插入的时间顺序,这n个数依次为:第1个插入的数,第2个插入的数,…第n个插入的数。 输入格式 第一行包含整数M,表示操作次数。 接下来M行,每行包含一个操作命令,操作命令可能为以下几种: (1) “H x”,表示向链表头插入一个数x。 (2) “D k”,表示删除第k个输入的数后面的数(当k为0时,表示删除头结点)。 (3) “I k x”,表示在第k个输入的数后面插入一个数x(此操作中k均大于0)。 输出格式 共一行,将整个链表从头到尾输出。 数据范围 1≤M≤1000001≤M≤100000 所有操作保证合法。 输入样例: 10 H 9 I 1 1 D 1 D 0 H 6 I 3 6 I 4 5 I 4 5 I 3 4 D 6 输出样例: 6 4 6 5 # include <iostream> using namespace std ; const int N = 100010 ; int head , idx , e [ N ] , ne [ N ] ; void

STL之List使用

感情迁移 提交于 2020-02-20 03:16:13
List 的使用: 定义:标准模板库实现的是双向链表,每个链表节点包含数据和指向下一个数据的指针。可以实现快速插入和删除,但是随机访问慢。 头文件:#include <list> 定义: List<elementtype> listname; 其他构造函数类似vector: 构造函数: list<elementtype>lst1; //创建空list list<elementtype> lst2(5); //创建含有5个元素的list list<elementtype>lst3(3,2); //创建含有3个元素初始值为2的list list<elementtype>lst4(lst2); //使用lst2初始化lst4 list<elementtype>lst5(lst2.begin(),lst2.end()); //同lst4 插入元素: Push_back();在链表尾部插入 Push_front();在链表头部插入 insert() 插入一个元素到list中 到指定位置 删除元素; pop_back() 删除最后一个元素 pop_front() 删除第一个元素 erase()删除指定元素 其他操作: assign() 给list赋值 back() 返回最后一个元素 begin() 返回指向第一个元素的迭代器 clear() 删除所有元素 empty()

HashMap知识初探

只谈情不闲聊 提交于 2020-02-19 17:53:52
public class TestHashMap { /** * HashMap是数组和链表组合构成的数据结构 * 数组里面每个地方都存了key-value这样的实例Java7叫Entry,Java8叫Node * 因为本身所有的位置都为null,在put插入的时候会根据key的hash去计算一个index值。 * 为什么需要链表? * 我们都知道数组长度是有限的,在有限的长度里面我们使用哈希,哈希本身就存在概率性,就是"12"和"21"我们都去hash有一定的概率会一样,如下面情况"12"和"21"hash到一个值上,那就形成了链表。 * * 数组容量是有限的,数据多次插入,到达一定的数量就会进行扩容,也就是resize * 扩容条件:Capacity:HashMap当前长度;LoadFactor:负载因子,默认值0.75f * 扩容分2步:1、扩容:创建一个Entry的空数组,长度是原数组的2倍 2、ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组 * * 为什么要重新Hash,直接复制过去不好吗? * 因为长度扩大以后,Hash的规则也随之改变 * Hash的公式---> index = HashCode(Key) & (Length - 1) * 原来长度(Length)是8你位运算出来的值是4 ,新的长度是16你位运算出来的值明显不一样了。 *

小白算法积累——单链表11#带头结点单链表 +分解+逆序

蓝咒 提交于 2020-02-19 11:36:33
题目 :设C={a1,b1,a2,b2,…an,bn}为线性表,采用带头结点的hc单链表存放, 设计一个就地算法,将其拆分为两个线性表, 使得A={a1,a2,…an},B={bn,bn-1,…b2,b1} 关键字 :带头结点单链表 +分解+逆序 思路1 采用第10题的思路,借助访问序号小助手 思路2 不使用序号小助手 while循环中的代码改为将结点插入到表A中并将下一个结点插入到B中, 然后逐步循环这个操作,one for A,one for B ||one for A,one for B ||… 另外,由于B是逆置,所以使用头插法 需要变量: A,B表头结点指针:A,B A表(旧表)的工作指针p,尾指针ra (执行尾插法),后继指针q(防断链) LinkList DisCreat_2 ( LinkList & A ) { LinkList B = ( LinkList ) malloc ( sizeof ( LNode ) ) ; //创建B表表头 B -> next = NULL ; //初始化B表 LNode * p = A -> next , * q ; //p为工作指针,q为 LNode * ra = A ; //ra为表尾指针,始终指向A的尾结点 while ( p != NULL ) { ra -> next = p ; ra = p ; //ra作为尾指针

单向环形链表 约瑟夫问题

孤者浪人 提交于 2020-02-19 09:08:56
Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。 链表如下图 数2下 自己也要数 所以只会移动1次 构建链表,遍历链表 分析图 first.next = 2 3.next = first 让最后一个元素的next指向first 首先 创建一个环形链表 // 创建一个first节点,当前没有编号 private Boy first = null; // 添加小孩节点,构建成一个环形的链表 public void addBoy(int nums) { // nums 做一个数据校验 if (nums < 1) { System.out.println("nums的值不正确"); return; } Boy curBoy = null; // 辅助指针,帮助构建环形链表 // 使用for来创建我们的环形链表 for (int i = 1; i <= nums; i++) { // 根据编号,创建小孩节点 Boy boy = new Boy(i); // 如果是第一个小孩 第一次 if (i == 1) { first = boy; //这是头指针 把第一个的赋值给first //不太理解

归并排序指针版及链表版

ε祈祈猫儿з 提交于 2020-02-19 05:40:22
什么是归并排序    归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。   归并排序比较占用内存,但却是一种 效率高且稳定 的算法。其时间复杂度为 O(n log n) ,空间复杂度为 T(n)。其速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。   个人觉得一般归并排序用于链表的排序有奇效! 思路   归并排序的主要思想是 分治 。   主要过程是: 1.将n个元素从中间切开,分成两部分。(左边可能比右边多1个数) 2.将步骤1分成的两部分,再分别进行递归分解。直到所有部分的元素个数都为1。 3.从最底层开始逐步合并两个排好序的数列为一个有序的数列。 图片取自https://www.cnblog.com/chengxiao/p/6194356.html 指针版: # include <stdio.h> # include <string.h> # include <stdlib.h> void sort ( int x , int y , int * st ) ; //将数组分开 void Link ( int x

C语言经典例74-连接两个链表

别来无恙 提交于 2020-02-19 04:33:38
目录 1 题目 2 分析 3 实现 4 运行结果 1 题目 连接两个链表,如有链表 A 和链表 B ,将链表 B 按原顺序接在链表 A 后面,链表结构为: typedef int ElementType ; typedef struct node { ElementType data ; struct node * Next ; } * List ; 2 分析 本题在逻辑上很简单,不难想出只要得到链表 A 的最后一个节点指针,然后将其指向链表 B 的第一个节点即可,注意创建链表时,链表带头节点,实际上链表 B 的第一个节点为链表 B 的头节点的下一个节点 B->Next (程序的第 57 行)。 3 实现 # include <stdio.h> # include <stdlib.h> # include <time.h> # include <unistd.h> typedef int ElementType ; typedef struct node { ElementType data ; struct node * Next ; } * List ; // 创建链表 List CreateList ( void ) { List L = ( List ) malloc ( sizeof ( struct node ) ) ; L -> data = 0 ; L ->

LeetCode刷题-- 双指针

被刻印的时光 ゝ 提交于 2020-02-19 04:27:09
26. 删除数组中的新元素 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 示例 1: 给定数组 nums = [1,1,2], 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 示例 2: 给定 nums = [0,0,1,1,1,2,2,3,3,4], 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 class Solution { public int removeDuplicates ( int [ ] nums ) { //i指向要保留的数; //j遍历整个数组 int i = 0 ; for ( int j = 1 ; j < nums . length ; j ++ ) { if ( nums [ i ] != nums [ j ] ) { i ++ ; //找到了需要保留的数字,让i后移,腾出位置 nums [ i ] = nums [ j ] ; } } return i + 1 ; } } 633. 平方数之和 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c。 示例1: 输入: 5 输出: