算法通关村-Hash和队列基础知识

2023-12-13 11:22:59

〇、前言

1.上期回顾

? ? ? ? 在上期我们讲到了如何利用栈解决经典问题,有效的括号问题。栈并不难理解重要的是我们要在做题的时候想到这个线性结构,当然不止这个问题,还有一些经典问题,计算器问题、逆波兰式问题等都可以用栈来解决。有兴趣的同学可以去学习了解。

2.本章内容

? ? ? ? 本章我们将要讲到的是Hash和队列。

一、Hash基础

1.概念和基本特征

概念:哈希(Hash)也称散列,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,这个输出值就是散列值。简单来说就是将一种任意长度的消息压缩到某一固定长度的消息摘要的函数。

特征:转换是压缩映射,散列值的空间通常远小于输入的空间。不同的输入可能会散列成相同的输出。

2.碰撞处理方法

碰撞:输入两个不同的输入值,根据同一散列函数计算出的散列值相同的现象叫做碰撞。

常见解决方法:开放定址法(Java里的Threadlocal)、链地址法(Java里的ConcurrentHashMap)、再哈希法(布隆过滤器)、建立公共溢出区。后两种用的比较少,我们重点看前两个。

开放地址法

开放地址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。

例如上面要继续存7 ,8,9的时候,7没问题,可以直接存到索引为0位置。8本来应该存到索引为1的位置,但是已经满了,所以继续向后找,索引3的位置是空的,所以8存到3位置。同理9存到索引6位置。

链地址法

链地址法将哈希表的每个单元作为链表的头结点,所有哈希地址为i的元素构成一个同义词链表。即发生冲突时就把该关键字链在以该单元为头结点的链表的尾部。?

二、队列基础

1.概念和基本特征

概念:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头

特征:节点的排队次序和出队次序按入队时间先后确定,即先入队者先出队,后入队者后出队,即我们常说的FIFO(first in first out)先进先出。

2.队列的实现

两种形式,基于数组和基于链表。这边我们暂时只看基于链表实现。

基于链表:因为链表的长度是随时都可以变的,实现起来比较简单。基于链表实现队列还是比较好处理的,只要在尾部后插入元素,在front删除元素就行了。

代码

public class LinkQueue {
    private Node front;
    private Node rear;
    private int size;

    public LinkQueue() {
        this.front = new Node(0);
        this.rear = new Node(0);
    }
    /**
     * 入队
     */
    public void push(int value) {
        Node newNode = new Node(value);
        Node temp = front;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
        rear = newNode;
        size++;
    }

    /**
     * 出队
     */
    public int pull() {
        if (front.next == null) {
            System.out.println("队列已空");
        }
        Node firstNode = front.next;
        front.next = firstNode.next;
        size--;
        return firstNode.data;
    }

    /**
     * 遍历队列
     */
    public void traverse() {
        Node temp = front.next;
        while (temp != null) {
            System.out.print(temp.data + "\t");
            temp = temp.next;
        }
    }

    static class Node {
        public int data;
        public Node next;

        public Node(int data) {
            this.data = data;
        }
    }

    //测试main方法
    public static void main(String[] args) {
        LinkQueue linkQueue = new LinkQueue();
        linkQueue.push(1);
        linkQueue.push(2);
        linkQueue.push(3);
        System.out.println("第一个出队的元素为:" + linkQueue.pull());
        System.out.println("队列中的元素为:");
        linkQueue.traverse();
    }
}

文章来源:https://blog.csdn.net/qq_52346133/article/details/132729870
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。