• 数据结构与算法


    数据结构与算法

    什么是数据结构

    • 数据项:一个数据元素可以由若干数据项组成
    • 数据对象:由相同性质的数据元素的集合,是数据子集
    • 数据结构:相互之间存在的一种或多种特定关系数据元素的结合

    逻辑结构和物理结构

    • 逻辑结构:是指数据对象中数据元素之间的相互关系
      • 集合结构
      • 线性结构
      • 树形结构
      • 图形结构
    • 物理结构
      • 顺序存储结构
      • 链式存储结构

    线性表与链表篇

    线性表之顺序表

    类的关系

    什么情况下使用ArrayList?

    优点

    • 尾插效率高,支持随机访问(内部使用数组)

    缺点

    • 中间插入或者删除效率低(整个数组进行位移,ararycopy )

    应用

    • 需要进行排序,不要用ArrayList。linkedlist好用
    • 很少的删除操作用 ArrayList

    在索引中ArrayList的增加或者删除某个对象的运行 过程?效率很低吗?解释以下为什么?

    效率低,因为反复的Arraycopy。耗内存,耗时间

    ArrayList如果顺序删除节点?

    通过本身的迭代器顺序删除节点

    for循环也可以 删除,但必须从尾部开始

    ArrayList的遍历方法

    next()

    foreach()方法

    链表

    用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。

    • 单向链表
    • 双向链表

    单链表分析

    • 随意增加删除,插入效率高,长度可以随意更改
    • 内存上不连续,不能随机查找

    应用

    • 要进行排序,要用LinkedList

    双链表分析

    • 删除后孤立的节点会被 JVM自动回收
    • 查找速度比单链表快一倍

    面试总结

    ArrayList和LinkedList有什么区别?

    list总结

    好文章推荐 内存

    什么是内存缓存

    预先将数据写到容器(list,map,set)等数据存储单元中,就是内存缓存

    链表实现LRU算法

    是吗是URL算法

    内存缓存淘汰机制

    • FIFO (First in First Out)
    • LFU(Least Frequently Used) 最不经常使用的
    • LRU (Least Recently Used) 最近使用的保留时间长

    代码实现:

    自定义链表:

    package 数据结构;
    
    public class LinkedList<T> {
    
        Node list;
        int size;//多少个节点
        public LinkedList(){
            size = 0;
        }
        //增加节点
        //在头部添加
        public void put(T data) {
            Node head = list;
            Node curNode = new Node(data, list);
            list = curNode;
            size++;
        }
        //检查Index是否在链表范围以内
        public void checkPositionIndex(int index) {
            if(!(index>=0&&index<=size)){
                throw new IndexOutOfBoundsException("Index:" + index+",size:"+size);
            }
        }
        //在链表index位置插入数据
        public void put(int index,T data) {
            checkPositionIndex(index);
            Node cur = list;
            Node head = list;
            for(int i = 0; i < index; i++) {
                head = cur;
                cur = cur.next;
            }
            Node node = new Node(data, cur);
            head.next = node;
            size++;
    
        }
    
    
        //删除节点
        //删除头部节点
        public T remove(){
            if(list != null){
                Node node =list;
                list = list.next;
                node.next = null;//GC回收
                size--;
                return node.data;
            }
            return null;
        }
        public T remove(int index){
            checkPositionIndex(index);
            Node cur = list;//拿到链表头部
            Node head = list;
            for(int i = 0;i<index;i++){
                head = cur;
                cur = cur.next;
            }
            head.next = cur.next;
            cur.next = null;//Gc回收
            return cur.data;
        }
    
        public T removeLast(){
            if(list != null){
                Node node = list;
                Node cur = list;
                while (cur.next != null){
                    node = cur;
                    cur = cur.next;
                }
                node.next = null;
                size--;
                return cur.data;
            }
            return null;
        }
        //修改节点
        public void set(int index,T newData){
            checkPositionIndex(index);
            Node head = list;
            for(int i = 0;i<index;i++){
                head = head.next;
            }
            head.data = newData;
    
        }
        //查询节点
        //get 头节点
        public T get(){
            Node node =list;
            if(node!=null){
                return node.data;
            }else {
            return null;
            }
        }
    
        public T get(int index){
            checkPositionIndex(index);
            Node node = list;
            for (int i = 0;i < index;i++){
                node = node.next;
            }
            return node.data;
        }
        //节点信息
        class Node{
            T data;
            Node next;
    
            public Node(T data,Node node) {
                this.data = data;
                this.next = node ;
            }
        }
        @Override
        public String toString() {
            Node node = list;
            for (int i = 0; i < size; i++) {
                System.out.print(node.data + " ");
    //			System.out.print(" ");
                node = node.next;
            }
            System.out.println();
            return super.toString();
        }
        //LRU添加节点
        public void lruPut(T data){
    
        }
    
        public static void main(String[] args) {
            LinkedList<Integer> list = new LinkedList<>();
            for(int i = 0; i < 5; i++) {
                list.put(i);
            }
            list.toString();
            list.put(3,3);
            list.toString();
            list.put(8);
            list.toString();
            System.out.println(list.get(2));
    
    
        }
    }
    ================================================
    4 3 2 1 0 
    4 3 2 3 1 0 
    8 4 3 2 3 1 0 
    3
    

    Lru算法实现

    package 数据结构;
    
    public class LruLinkedList<T> extends LinkedList<T> {
    
        int memory_size;// 用于限定内存空间大小,也是缓存的大小
        static final int DEFAULT_CAP = 5;
    
        public LruLinkedList(){
            memory_size = DEFAULT_CAP;
        }
        public LruLinkedList(int default_memory_size){
            memory_size = default_memory_size;
        }
        //增加 Lru节点
        public void LruPut(T data){
            if(size >= memory_size){
                removeLast();
                put(data);
            }else {
                put(data);
            }
        }
        //Lru删除
        public T Lruremove(){
            return removeLast();
        }
        //lru 访问
        public T Lruget(int index){
            checkPositionIndex(index);
            Node node = list;
            Node pre = list;
            for (int i = 0; i < index; i++){
                pre = node;
                node = node.next;
            }
            T resultData = node.data;
            // 将访问的节点移到lisk的表头
            pre.next = node.next;
            Node head = list;
            node.next = head;
            list = node;
            return resultData;
    
    
        }
    
        public static void main(String[] args) {
            LruLinkedList<Integer> lruLinkedList = new LruLinkedList<>();
            for (int i = 0; i<4;i++){
                lruLinkedList.put(i);
            }
            lruLinkedList.toString();
            System.out.println(lruLinkedList.Lruget(3));
            lruLinkedList.toString();
            lruLinkedList.LruPut(20);
            lruLinkedList.toString();
            lruLinkedList.LruPut(5);
            lruLinkedList.toString();
        }
    }
    ====================================================
    3 2 1 0 
    0
    0 3 2 1 
    20 0 3 2 1 
    5 20 0 3 2 
    

    队列和栈

    Java线程操作

    什么是队列

    队列又叫先进先出表,一种运算受限的线性表 。

    入队叫 队头

    出队 叫 队尾

    队列做缓存中比较常用

    • 队列为空,队头队尾指向同一个节点
    • 假移除 队头前面空着(有的走了)队尾满了 到头了(继续增加,发生假溢出)

    **循环队列 **

    队列存储结构-链式存储

    队列的链式存储结构,其实就是线性表的单链表,只不过只能从尾进头出。

    作业:实现循环队列

    队列的变行

    双端队列

    优先级队列

    手机页面切换等用的就是栈

    后进先出表

    顺序结构:数组实现

    链式结构:链表实现

    栈的面试题

    Java的Stack是通过Vector来实现的,这种设计被认为是不良的设计,说说你的看法。

    vector实现了很多栈不用的方法,例如add[index,object ] 索引插入等,Java程序员偷懒,完全可以自己实现一个

    作业:用栈和队列实现逆波兰序列

    栈用来存 操作符

    队列来存 操作数

    JVM内存栈

    • StackoverflowError 栈溢出
    • 递归的函数调用,容易出现栈溢出。超出了栈的大小
    • OutOfMemoryError 堆溢出

    栈和堆得区别

    • 栈解决了程序的运行问题,即程序如何指向,如何处理数据
      • 负责 运算逻辑
      • 栈分为栈帧,每个栈帧为 4byt Java中每个引用占一个栈帧(slot)
    • 堆解决了数据存储的问题,即数据放在那,怎样放
      • 负责存储逻辑

    Stack和heap都运行在内存上,在内存空间上字节码指令不必担心不同机器上的区别,所以JVM实现了平台无关性

    JVM控制了栈和堆的大小。

    深入解刨HashMap

    **你不知道而又必须指定的原理 **

    ArrayList 基于数组实现的

    Hash表 结合了 顺序表和链表

    • 用顺序存储数据,保存数据的方式(动态增值,动态删除)
    • 链表练习下面节点

    顺序表和链表的结合

    为啥叫Hash表,

    • object有一个HachCode函数(永远都是Int类型,目的就是得到一个int类型的Hash值,根据int值求 <key,value>)
    • 通过 把key hash得到一个整数型数据,再对table的length求模,得到table 对应得[index] (table是数组),然后得到table[index] 的 value
    • 如果key1 key2 key3 相等
      • 发生hash冲突
      • key1 index1
      • key2 index1 存在 key1后面 链表的形式存储。
      • key3 index3
    • **key的作用就是快速定位 **
    • value
    • hash把一个 与 int无关的类型转换成了int下标
    • hash用作位运算(计算机 位运算 效率最高)
    • hashmap也用位运算

    往hash表里面添加节点,添加到节点头部

    什么是HashMap

    key value 键值对

    **扩容 **

    当 hash表满了 就要 扩容。

    加载因子

    例子 加载因子=0.75

    数组大小 位 16

    则当 存储了12 个节点后 就满了

    然后就要扩容

    threadLocalHashCode

    一个线程对应一个ThreadLocalMap

    一个map对象多个键值对。

    • key 是ThreadLocal
    • value是v

    多线程必定会用到的,运用了 hashMap的思想

    总结:

    集合总统架构

  • 相关阅读:
    Feed back TFS 2017 RC upgrade status to product team in product group 2017.03.01
    TFS Training for Kunlun bank (http://www.klb.cn/) 微软研发流程(ALM)管理培训会议(昆仑银行) 2016.09.21
    微软DevOps软件开发高级培训课程(深圳站) 2016.04.06
    秒杀系统架构设计
    程序员职业规划
    程序员跳槽时,会遇到哪些套路?
    程序员3大点
    程序员37个小贴士
    程序员6大点
    程序员面试 10 大潜规则
  • 原文地址:https://www.cnblogs.com/AronJudge/p/14489575.html
Copyright © 2020-2023  润新知