逻辑结构
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);
}
}