数据结构学习(基础)——链表——Day04

2.1 哈希表、有序表、单链表和双链表

HashMap就是Key-Value成对出现;HashSet就是可以只有key没有value,两者区别就是有没有伴随数据。

哈希表是无序组织的key

HashMap:put方法既是添加数据也是更新数据,当put中key在Map中没有就是添加,如果有的话就更新key的value值;同时也可以remove(key),删除key同时删除掉伴随数据。查的话,我们可以用containKey方法查这个key是不是存在同时也可以利用get方法查询key所对应的value。

HashSet:add,remove就是添加和删除,可以看这个元素是否存在与Set;contain方法查询key是否存在

哈希表在使用的时候时间复杂度都是常数级别(增、删、改、查)。

①哈希表的简单介绍

    1>哈希表在使用层面可以理解为一种集合结构。

    2>如果只有key,没有伴随数据value,可以使用HashSet结构

    3>如果既有key,又有伴随数据value,可以使用HashMap结构

    4>有无伴随数据,是HashSet和HashMap唯一区别,底层的实际结构是一回事

    5>使用哈希表增(put)、删(remove)、改(put)和查(get)的操作,可以认为时间复杂度为O(1),但是常数时间比较大

    6>放入哈希表的东西,如果是基础类型,内部按值传递,内存占用就是这个东西的大小

    7>放入哈希表的东西,如果不是基础类型,内部按引用传递,内存占用是这个东西内存地址的大小(占用8byte)

TreeSet:只有key

TreeMap:有key和value

有序表是有序组织的key,哈希表能完成的功能有序表都能完成,同时还能根据key有序来添加功能

put:既是添加,又是更新,而且key是可以进行比较的,比如可以找出所有key中的最大和最小,或者小于等于某个key大于等于某个key。性能比哈希表差一点。增删改查都是O(logN)级别的

②有序表的简单介绍

    1>有序表在使用层面上可以理解为一种集合结构

    2>如果只有key,没有伴随数据value,可以使用TreeSet结构

    3>如果既有key,又有伴随数据value,可以使用TreeMap结构

    4>有无伴随数据,是TreeSet和TreeMap唯一的区别,底层的实际结构是一回事

    5>有序表和哈希表的区别是,有序表把key按照顺序组织起来,而哈希表完全不组织

    6>红黑树、AVL树,size-balance-tree和跳表都属于有序表结构,只是底层具体实现不同

    7>放入有序表的东西,如果是基础类型,内部按值传递,内存占用就是这个东西的大小

    8>放入有序表的东西,如果不是基础类型,必须提供比较器,内部按引用传递,内存占用是这个东西内存地址的大小

    9>不管是什么底层具体实现,只要是有序表,都有一下固定的基本功能和固定的时间复杂度

有序表的固定操作:

    1>void put(K key,V value):将一个(key,value)记录加入到表中,或者将key的记录更新成value

    2>V get(K key):根据指定的key,查询value并返回

    3>void remove(K key):移除key的记录

    4>Boolean containKey(K key):询问是否有关于key的记录

    5>K firstKey():返回所有键值的排序结果中,最左(小)的那个

    6>K lastKey():返回所有键值的排序结果中,最右(大)的那个

    7>K floorKey(K key):如果表中存入过key,返回key;否则返回所有键值的排序结果中,key的前一个

    8>K ceilingKey(K key):如果表中存入过key,返回key;否则返回所有键值的排序结果中,key的后一个

单向链表和双向链表都是,给一个头部head就可以找到后面的节点

一个节点的属性next是下一个节点

问题1:分别实现反转单向链表和双向链表的函数(要求时间复杂度为O(N),额外空间复杂度O(1)

/**
     * 1.反转单项链表
     * 1->2->3 变成1<-2<-3
     */
    public static singleNode reverseSingleNode(singleNode head){//传来一个头部
        if(head == null || head.next == null){//如果head为null代表链表为空,返回null,如果head的下一个为null代表该链表就只有一个节点返回该节点
            return head;
        }
        //定义该节点的上一个和下一个节点
        //链表连接节点是通过next,无法回溯,所以我们定义preNode,而如果我们完成1 2节点的反转,就会丢失2 3节点的连接,所以我们要通过nextNode完成连接 用于保存上一个和下一个节点
        singleNode preNode = null;
        singleNode nextNode = null;

        //当head为null的时候就代表已经反转完最后一个了
        while(head != null){
            nextNode = head.next;//需要将下一个节点的地址保存下来,否则我们将这个链表反转后,我们会找不到下一个链表,也就是我们的head找不到下一个node了
            head.next = preNode;//将当前节点的next指向前一个节点的地址    完成1 2 节点的反转后,2 3 之间就没有next作为连接了,所以还想继续完成反转,我们需要让下一个节点
            //
            preNode = head;//由于你当前节点已经完成了链翻转,而我们依旧要完成下一个链的翻转,所以我们要让当前节点成为下一个节点的前一个(虽然已经断开连接)
            head = nextNode;//我们需要将head移动到下一个节点的地址
        }
        return preNode;//这就是源链表的最后一个数也就是翻转后链表的头节点
    }

    /**
     * 2.反转双向链表
     * @param head
     * @return
     */
    public static doubleNode reverseDoubleNode(doubleNode head){
        if(head == null || head.next == null){//如果head为null代表链表为空,返回null,如果head的下一个为null代表该链表就只有一个节点返回该节点
            return head;
        }
        doubleNode nextNode = null;//定义下一个节点因为我们完成该节点和上一个节点的连接反转后,无法通过next或者是pre找到下一个节点,所以我们先把下一个节点保存下来方便寻找
        doubleNode temp = null;//定义当前节点,用于最后返回
        //当head为null的时候就代表已经反转完最后一个了
        while (head != null){
            nextNode = head.next;//将下一个节点先保存下来,避免找不到
            head.next = head.pre;//将当前节点的next指针换到前一个节点,也就是当前节点的pre
            head.pre = nextNode;//该节点的pre指针指到将保存起来的节点(原链表中的下一个节点)
            //完成next和pre的变换后,我们需要换head
            //需要一个变量保存当前值,用于返回
            temp = head;//为什么要这个?     因为要保存当前节点用于最后的返回,节点后移继续反转
            //将head移动到下一个节点,我们之前保存过那个地址
            head = nextNode;
        }
        return temp;
    }

问题2:给定两个有序链表的头指针head1和head2,打印两个链表的公共部分(要求时间复杂度为O(n),额外空间复杂度O(1))

有点类似于外部排序的过程

/**
     * 3.给定两个有序链表的头指针head1和head2,打印两个链表 的公共部分(要求时间复杂度为O(n),额外空间复杂度O(1))
     * 主体思想:
     * 两个链表定义两个指针分别指向链表头部,判断两个指针所指向的节点的value是不是相同,如果相同一起向下移动,如果第一个小于第二个的话第一个下移第二个不动,反之亦然。
     */
    public static void xiangtongLianBiao(singleNode s1,singleNode s2){//传参的时候可以传入两个链表的头部节点
        //定义两个指针表明链表的当前位置
        singleNod

你可能感兴趣的:(数据结构,学习,链表)