自学 数据结构(二)逻辑结构

逻辑结构

1. 集合结构

List

ArrayList
定义:有序可重复 ArrayList 数据结构是数组。查询快,增删慢。ArrayList是线程不安全的,允许元素为null 。
代码实例:https://www.runoob.com/java/java-arraylist.html

Vector
定义: 线程安全的数组,效率较差,已经过时不用。
代码地址:https://www.runoob.com/java/java-vector-class.html

LinkedList
定义: LinkedList 数据结构是双向链表,插入删除比较方便。LinkedList 是线程不安全的,允许元素为null 。
代码实例:https://www.runoob.com/java/java-linkedlist.html

Map

HashMap :
定义:jdk1.8中HashMap底层是哈希表数据结构,数组+链表+红黑树,HashMap是线程不安全的,允许使用null键和null值, HashMap根据键的HashCode值存储数据,具有很快的访问速度。
HashMap存入的键值对在遍历时的顺序是随机的。
不支持并发
代码实例:https://www.runoob.com/java/java-hashmap.html

HashTable:
定义:线程安全,使用synchronized锁住全部数据,效率较低,不允许使用null键和null值。
代码实例:https://www.runoob.com/java/collection-hashtable-key.html

LinkedHashMap:
定义: LinkedHashMap 是HashMap的一个子类,默认LinkedHashMap遍历时输出的顺序和put输入的顺序是相同的。
LinkedHashMap有两种排序方式:插入排序和访问排序(修改或访问一个元素后,将该元素移到队列末尾),默认是插入排序。使用accessOrder来标记使用哪种排序方式,accessOrder==true时,表示使用访问排序,默认为false;
LinkedHashMap使用了双向链表来保证了顺序性。
在这里插入图片描述

TreeMap:
定义:TreeMap底层是红黑树数据结构,线程不安全,可以用于给Map集合中的键进行排序
TreeMap遍历出来的是排序后的键值对。 ConcurrentHashMap
ConcurrentHashMap是线程安全的,jdk1.8使用CAS和volatile实现。而jdk1.8以前通过锁分段技术、可重入锁实现。
支持并发,可以一边更新一边遍历

Set

LinkedHashSet
定义:在添加一个元素时,先求hash值,再求索引,确定该元素在hashtable的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加(原则和HashSet一样))

HashSet
定义:存放键值对,无序不重复。
代码实例:https://www.runoob.com/java/java-hashset.html

SortedSet
有序的Set,通过SortedMap来实现的

TreeSet
定义:TreeSet的性能比HashSet差,简单比较:HashSet使用散列表进行存储,元素无序,元素允许为null。TreeSet是使用树结构来进行存储,元素按字符串顺序排序存储,元素不允许为null。

集合的父类:Iterable -> Collection -> (List-Set)

2. 线性结构


定义:栈的实现可以用顺序也可以用链式。它遵循先进后出原则
代码实例:https://www.runoob.com/java/data-stack.html

队列
定义:队列只能允许在队头、队尾进行添加和查询等相关操作。
代码实例:https://www.runoob.com/java/data-queue.html

数组
定义:数组通常被用来表示数组数据类型,它由一组值或变量组成,这些值或变量可以由一个或多个在运行时计算的索引来选择。数组类型通常由数组结构来实现;然而,在某些语言中,它们可能是由哈希表、链表、搜索树或其他数据结构实现的。
代码实例:https://www.runoob.com/java/arrays-search.html

链表
定义:链表是由一系列节点组成的元素结合。每个节点包含两个部分,数据域item和指向下一个节点的指针next。通过节点之间的相互连接,最终串联成一个链表。
代码实例:https://www.runoob.com/java/data-insert.html

3. 树形结构

一个树形结构的外层和内层有相似的结构, 所以这种结构多可以递归的表示。经典数据结构中的各种树形图是一种典型的树形结构:一颗树可以简单的表示为根, 左子树, 右子树。 左子树和右子树又有自己的子树。
代码实例:

import java.util.ArrayList;
import java.util.List;

public class TreeNode {
    private int age;    // 节点属性,年龄
    private String name;   //节点属性,姓名

    TreeNode proTreeNode;    //上级节点
    List<TreeNode> list = new ArrayList<TreeNode>(); //孩子节点
  public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public TreeNode getProTreeNode() {
        return proTreeNode;
    }

    public void setProTreeNode(TreeNode proTreeNode) {
        this.proTreeNode = proTreeNode;
    }

    public void addTreeNode(TreeNode treeNode){
        list.add(treeNode);
        treeNode.proTreeNode = this;
    }

    public TreeNode getTreeNode(Integer i){
        return list.get(i);
    }

    public void removeTreeNode(TreeNode treeNode){
        list.remove(treeNode);
        treeNode.proTreeNode = null;
    }
    public String toString(){
        return "姓名:"+name+";年龄:"+age+"。";
    }
}

/**
 * 创建一个树结构:
 *
 *           李磊
 *        |         |
 *    韩梅梅       丽丽
 *                   |
 *                 李刚
 */
public class TreeStructure {
    public static void main(String[] args) {
        TreeNode treeNode0 = new TreeNode();
        treeNode0.setAge(11);
        treeNode0.setName("李磊");

        TreeNode treeNode1 = new TreeNode();
        treeNode1.setAge(13);
        treeNode1.setName("韩梅梅");

        TreeNode treeNode2 = new TreeNode();
        treeNode2.setAge(15);
        treeNode2.setName("莉莉");

        TreeNode treeNode3 = new TreeNode();
        treeNode3.setAge(15);
        treeNode3.setName("李刚");

        treeNode0.addTreeNode(treeNode1); //父节点关联孩子节点
        treeNode0.addTreeNode(treeNode2); //父节点关联孩子节点

        treeNode2.addTreeNode(treeNode3); //丽丽节点下挂李刚

        System.out.println(treeNode1);   //打印节点本身
        System.out.println(treeNode2.getTreeNode(0));  //打印树节点
        System.out.println(treeNode1.getProTreeNode());  //打印父接口
    }
}

在这里插入图片描述

4. 图形结构

概念:
节点可以具有零个或多个相邻元素,两个节点的连接称之为边,节点在图形结构中也被称为顶点,一个顶点到另一个顶点的经过的的线路称为路径。

思路:
从当前顶点选一个与之连接而未访问过的顶点,将当前节点往该邻接顶点移动,如果邻接顶点没有未访问的,则回溯到上一个顶点位置,继续该步骤。直到所有顶点都访问过。

图形结构有3种类型:无向图、有向图、带权图

无向图:顶点A与顶点B之间的边是无方向的,可以从A到B,也可以从B到A

有向图:顶点A与顶点B之间的边是有方向的,可以从A到B,但不可以从B到A

带权图:顶点A与顶点B之间的边是带有属性的,如A到B的 距离。

以下图借用:
在这里插入图片描述代码实例:

package org.scbit.wuzi.util;

public class Graph {
    private int vertexSize;//顶点数量
    private int [] vertexs;//顶点数组
    private int[][] matrix;//邻接矩阵
    private final static int MAX_WEIGHT = 1000;//权值即图的无穷大。这里只是做了最大的定义


    public Graph(int vertexSize) {
        super();
        this.vertexSize = vertexSize;
        matrix = new int[vertexSize][vertexSize];
        vertexs = new int[vertexSize];
        for (int i = 0; i < vertexSize; i++) {
            vertexs[i] = i;
        }
    }

    public int[] getVertexs() {
        return vertexs;
    }

    public void setVertexs(int[] vertexs) {
        this.vertexs = vertexs;
    }

    /**
     * 计算顶点的出度  横排是出度,竖列是入度
     * */
    public int getOutDegree(int index){
        int degree = 0;
        for (int j = 0; j < vertexSize; j++) {
            int weight = matrix[index][j];
            if (weight != 0 && weight !=MAX_WEIGHT){
                degree++;
            }
        }
        return degree;
    }

    /**
     * 计算顶点的入度  横排是出度,竖列是入度
     * */
    public int getIntDegree(int index){

        int degree = 0;
        for (int j = 0; j < vertexSize; j++) {
            int weight = matrix[j][index];
            if (weight != 0 && weight !=MAX_WEIGHT){
                degree++;
            }
        }
        return degree;
    }

    /**
     * 获取两个顶点之间的权值
     * @return
     */
    public int getWeight(int v1 , int v2) {
        int weight = matrix[v1][v2];
        return weight == 0 ? 0:(weight == MAX_WEIGHT?-1:weight);
    }

    //获取V1的邻接点 V1的出度点 V1的入度点
    //V2-V4的最短路径 拓普排序

    public static void main(String[] args) {
        Graph graph = new Graph(5);
        int[] a0 = new int[]{0,MAX_WEIGHT ,MAX_WEIGHT, MAX_WEIGHT, 6};
        int[] a1 = new int[]{9,0 ,3, MAX_WEIGHT, MAX_WEIGHT};
        int[] a2 = new int[]{2,MAX_WEIGHT ,0, 5, MAX_WEIGHT};
        int[] a3 = new int[]{MAX_WEIGHT,MAX_WEIGHT ,MAX_WEIGHT, 0, 1};
        int[] a4 = new int[]{MAX_WEIGHT,MAX_WEIGHT ,MAX_WEIGHT, MAX_WEIGHT, 0};
        graph.matrix[0] = a0;
        graph.matrix[1] = a1;
        graph.matrix[2] = a2;
        graph.matrix[3] = a3;
        graph.matrix[4] = a4;

        int degree = graph.getOutDegree(4);
        System.out.println("V" + 4 + "的出度是" + degree);

        int degree2 = graph.getIntDegree(0);
        System.out.println("V" + 0 + "的入度是" + degree2);
        int weight = graph.getWeight(0, 0);
        System.out.println("V0 - V4" + "的权值是" + weight);
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值