hashmap头插法和尾插法区别(数据结构头插法和尾插法)

admin 249 0

其实hashmap头插法和尾插法区别的问题并不复杂,但是又很多的朋友都不太了解数据结构头插法和尾插法,因此呢,今天小编就来为大家分享hashmap头插法和尾插法区别的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

一、(8)ConcurrentHashMap 1.7和1.8的区别(简单版未完待续)

1.7: Segment+ HashEntry+ Unsafe

1.8:移除Segment,锁粒度更小, Synchronized+ CAS+ Node+ Unsafe

1.7:先定位 Segment,再定位桶,put全程加锁,没锁线程提前找桶位置,最多自旋64次获取锁,超过挂起。

1.8:移除Segment,类似HashMap,直接定位到桶,拿 first节点后判断,1、空CAS插入;2、-1扩容,则跟着一起扩容;3、else加锁put(类似1.7)

基本类似,value为volatile,保证修改的可见性,不需加锁。

1.7:和HashMap一样,只不过单线程执行,避免HashMap在1.7扩容时死循环,保证线程安全。

1.8:并发扩容,HashMap扩容1.8中由头插改尾插(避免死循环),ConcurrentHashmap也是,迁移从尾开始,扩容前桶的头部放 hash为-1节点,判断是否该桶被其他线程处理过

1.7:计算两次,不变返回,不一致,锁住所有Segment求和

1.8: baseCount存当前节点数,涉及baseCount并发环境下修改(未完成)

短时间大量插入,就是提高ConcurrentHashMap插入效率,尽量散列均匀和避免加锁两个点,但是面试官还在问还有什么思路没?

(1)扩容,配置合理容量大小和扩容因子,减少扩容

(2)锁资源争夺,put用synchonized对头节点加锁,尽可能避免锁等级。通过spread方法预处理,将hash冲突数据放一个组,每组单线程put操作,保证停留偏向锁,不升级

原文链接:https://blog.csdn.net/u013374645/article/details/88700927

二、【数据结构】单链表的建立——头插法与尾插法

1、【数据结构】单链表的建立——头插法与尾插法。

2、当我们准备采用单链表的形式来实现线性表,那么第一步我们需要考虑到的就是单链表的建立,也就是初始化的过程。而由于链表是一个动态的结构,它不需要预先分配空间,因此生成链表的过程是一个结点“逐个插入”的过程,而结点插入的位置是我们可以选择的,所以按照结点插入的位置可以将单链表的建立方法分为头插法和尾插法。

3、该算法的官方描述为∶从一个空表开始,重复读入数据,生成新结点,将读入数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头结点之后。

4、这里的重点就是:每次生成的新结点都是要与头结点相连接的,每个新结点都插在了原来第一个节点的前面。通过这种方法建立的链表是后来居前的,也就是链表是逆序的。因此,当有题目让我们实现线性表的逆序表示,就应该首先考虑头插法。

5、其中,指针H始终指向头结点,指针s指向新结点。①表示初始化空表②表示申请新结点并赋值③表示插入第一个结点④表示插入第二个结点(④-1和④-2代表了先后顺序)。整个图示过程展现了头插法的基本原理。

6、该算法的官方描述为∶从一个空表开始,重复读入数据,生成新结点将读入数据存放到新结点的数据域中,然后将新结点插入到当前链表的表尾结点之后。

7、这里的重点就是:生成的一个新结点是直接插入当前单链表的尾端,也就是让原来最后一个结点指向该新结点。这也是链表长度增长的一种最基本的方式。后来居后,生成的链表是顺序的。

8、其中指针H始终指向头结点,指针s指向新结点,指针r始终指向单链表的表尾。①表示初始化空表②表示申请新结点并赋值③表示插入第一个结点④表示插入第二个结点(④-1和④-2代表了先后顺序)

9、整个图示过程展现了尾插法的基本原理。

10、分析完头插法和尾插法,又到了辨析两者时间复杂度的经典问题。

11、每个节点:只需要移动一下它本身和头指针的指向即可,不需要移动其他的元素,实际也和其他的元素没有关系,所以单个节点的时间复杂度是O(n)。

12、整个链表:设单链表的总长度为n,在一个已有N个元素的单链表中插入元素,如果插入位置为x那么需要找到它的前驱才可以插入,最坏时间复杂度为O(n),时间复杂度也为O(n)

13、每个节点:只需要移动一下它本身和尾指针的指向即可,不需要移动其他的元素,实际也和其他的元素没有关系,所以单个节点的时间复杂度是O(1)。

14、整个链表:设单链表的总长度为n,在一个已有N个元素的单链表中插入元素,如果插入位置为x那么需要找到它的前驱才可以插入,最坏时间复杂度为O(n),时间复杂度也为O(n)。

三、头插法和尾插法哪种需要防止链表断裂

1、插入速度快(不需要遍历旧链表),头结点每次插入都会变化,头结点永远是最新的元素,遍历时是按照插入相反的顺序进行,由于头结点不断在变化,所以需要额外的维护头结点的引用,否则找不到头结点,链表就废了。

2、个人总结,他们的区别在于,如果是头插法的话,那么新元素直接作为头结点,next指针指向旧的头结点即可,非常方便迅速效率高。如果是尾插法的话,添加新元素时需要遍历旧链表,直到某个节点的next指针为空,说明这个节点是尾节点,修改这个尾节点的next指针为新添加的元素即可。

四、头插法和尾插法建立单链表的区别

因为单链表的特殊结构,即只能从头向尾遍历,所以向头插时所用的语句会比向尾插少几个,向尾插时还要多一个指针指向尾结点,而用头插法时就不用,但用头插法时最先输入的数据会排在链表的最后,输出时即变成了输入时的逆序输出,看起来不如用尾插法那样和输入的顺序一样的形势更舒服些

OK,本文到此结束,希望对大家有所帮助。