从表到图:Java常用数据结构

Java数据结构

一.稀疏数组

当一个二维数组有许多相同的默认值,记录了许多没有意义的数据,可将该数组转换为稀疏数组

实现思路:

原数组总行数原数组总列数原数组有效值个数
有效值1所在行有效值1所在列有效值1
有效值2所在行有效值2所在列有效值2
有效值n所在行有效值n所在列有效值n
public class main {
    public static void main(String[] args) {
        int a[][] = new int[8][8];  //8*8数组
        a[2][2] = 5;    //3行3列,值5
        a[4][6] = 9;    //5行7列,值9
        a[5][7] = 12;   //6行8列,值12
        int value = 0;   //统计有效值个数
        
        System.out.println("原始数组:");
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[0].length; j++) {
                if (a[i][j]!=0){
                    value++;
                }
                System.out.printf("%d\t",a[i][j]);
            }
            System.out.println();
        }
        System.out.println("-------------------------------------");

        //原始数组转换稀疏数组
        int b[][] = new int[value+1][3];//创建稀疏数组,大小为有效值+1行和3列
        b[0][0] = a.length;     //原数组总行数
        b[0][1] = a[0].length;  //原数组总列数
        b[0][2] = value;        //原数组有效值个数
        int row = 1;    //稀疏数组有效数据行行数,记录有效值
        for (int i = 1; i < a.length; i++) {
            for (int j = 0; j < a[0].length; j++) {
                if (a[i][j]!=0){
                    b[row][0] = i;  //第一列:有效值所在行
                    b[row][1] = j;  //第二列:有效值所在列
                    b[row][2] = a[i][j];    //第三列:有效值
                    row++;  //记录完一行跳转下一行
                }
            }
        }
        System.out.println("稀疏数组:");
        for (int[] hang : b) {
            for (int i : hang)
                System.out.printf("%d\t",i);
            System.out.println();
        }
        System.out.println("-------------------------------------");

        //稀疏数组还原
        int c[][] = new int[b[0][0]][b[0][1]];  //创建数组
        for (int i = 1; i < b.length; i++) {
            for (int j = 0; j < b[1].length; j++) {
                //在b[i][0]行,[b[i][1]列添加有效值:b[i][2]
                c[b[i][0]][b[i][1]] = b[i][2]; 
            }
        }
        System.out.println("还原数组:");
        for (int[] hang : c) {
            for (int i : hang)
                System.out.printf("%d\t",i);
            System.out.println();
        }
    }
}

在这里插入图片描述

二.链表

链表是一种物理存储单元上非连续、非顺序的存储结构,元素的逻辑顺序是通过链表中的指针链接次序实现的

链表由一个个节点组成,每个节点都指向下一个节点,最后一个节点的下个节点指向null

public class main {
    public static void main(String[] args) {

        Student student1 = new Student(1, "小A");
        Student student2 = new Student(2, "小B");
        Student student3 = new Student(3, "小C");
        Student student4 = new Student(4, "小D");
        Student student5 = new Student(5, "小E");
        SingleLinkedList singleLinkedList = new SingleLinkedList();
        
        singleLinkedList.add(student1);
        singleLinkedList.add(student2);
        singleLinkedList.add(student3);
        singleLinkedList.add(student4);
        singleLinkedList.add(student5);

        System.out.println("学生链表");
        singleLinkedList.list();

        //修改节点
        Student newStudent = new Student(3, "小明");
        singleLinkedList.update(newStudent);
        System.out.println("修改后:");
        singleLinkedList.list();

        //删除节点
        singleLinkedList.del(4);
        singleLinkedList.del(7);
        System.out.println("删除后:");
        singleLinkedList.list();
    }
}

class SingleLinkedList {
    //初始化头节点
    private Student head = new Student(0, "");

    public void add(Student student) {
        //移动遍历
        Student temp = head;
        //遍历链表,找到最后
        while (true) {
            //找到链表的最后
            if (temp.next == null) {
                break;
            }
            //如果没有找到最后, 将temp后移
            temp = temp.next;
        }
        //将最后这个节点的next指向新的节点
        temp.next = student;
    }


    public void update(Student newStudent) {
        Student temp = head;
        while (true) {
            if(temp.next==null){
                System.out.println("找不到该元素");
                break;
            }
            //找到要修改的元素
            if (temp.num == newStudent.num) {
                temp.name = newStudent.name;
                break;
            }
            //如果没有找到最后, 将temp后移
            temp = temp.next;
        }
    }

    public void del(int num) {
        Student temp = head;
        while (true) {
            if(temp.next==null){
                System.out.println("找不到该元素");
                break;
            }
            if (temp.next.num == num) {
                //将待删除的节点替换为它的下一个节点
                temp.next = temp.next.next;
                break;
            }
            temp = temp.next; //temp后移,遍历
        }
    }

    public void list() {
        Student temp = head;
        while (true) {
            //判断是否到链表最后
            if (temp.next == null) {
                break;
            }
            System.out.println(temp.next);
            //将temp后移
            temp = temp.next;
        }
    }
}

class Student {
    public int num;
    public String name;
    public Student next; //指向下一个节点

    public Student(int num, String name) {
        this.num = num;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student [编号=" + num + ", name=" + name +"]";
    }
}

在这里插入图片描述

三.队列(Queue)

队列是一个有序列表,可用数组和链表实现,遵循先入先出原则

队列在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。rear端称为队尾,front端称为队头

public class main {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<String>();
        Scanner scanner = new Scanner(System.in);
        for (int i = 0; i < 5; i++) {
            queue.offer(scanner.next());
        }
        System.out.println(queue);

        for (int i = 0; i < 2; i++) {
            System.out.println("poll元素:"+queue.poll());
        }
        System.out.println(queue);

        System.out.println("element元素:"+queue.element());
        System.out.println(queue);

        for (int i = 0; i < 2; i++) {
            System.out.println("再次添加:"+queue.offer(scanner.next()));
        }
        System.out.println(queue);
    }
}

在这里插入图片描述

四.栈(Stack)

栈是一个有序列表,可用数组和链表实现,遵循先入后出原则

栈中的元素只允许在同一端进行插入和删除,能进行增删的一端为栈顶(top),固定的一端为栈底(bottom)

public class main {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<String>();
        Scanner scanner = new Scanner(System.in);
        for (int i = 0; i < 5; i++) {
            stack.push(scanner.next());
        }
        
        System.out.println(stack);
        for (int i = 0; i < 2; i++) {
            System.out.println("弹出元素:"+stack.pop());
        }
        
        System.out.println(stack);
        for (int i = 0; i < 2; i++) {
            System.out.println("加入元素:"+stack.push(scanner.next()));
        }
        System.out.println(stack);
    }
}

在这里插入图片描述

五.哈希表(Hash table)

根据关键码值(Key value)而直接进行访问的数据结构。通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表

哈希表是由一块地址连续的数组空间构成的,其中每个数组都是一个链表,数组的作用在于快速寻址查找,链表的作用在于快速插入和删除元素,因此,哈希表可以被认为就是链表的数组

public class main {
    public static void main(String[] args) {
        //创建哈希表
        HashTab hashTab = new HashTab(7);
        String key = "";
        Scanner scanner = new Scanner(System.in);
        while(true) {
            System.out.println("add:  添加员工");
            System.out.println("list: 显示员工");
            System.out.println("find: 查找员工");
            System.out.println("del: 删除员工");
            key = scanner.next();
            switch (key) {
                case "add":
                    System.out.println("输入添加id和名字");
                    int id = scanner.nextInt();
                    String name = scanner.next();
                    Emp emp = new Emp(id, name);
                    hashTab.add(emp);
                    break;
                case "list":
                    hashTab.list();
                    break;
                case "find":
                    System.out.println("输入查找id和名字");
                    int id1 = scanner.nextInt();
                    String name1 = scanner.next();
                    Emp emp1 = new Emp(id1, name1);
                    hashTab.findEmpById(emp1);
                    break;
                case "del":
                    System.out.println("输入删除id和名字");
                    int id2 = scanner.nextInt();
                    String name2 = scanner.next();
                    Emp emp2 = new Emp(id2, name2);
                    hashTab.del(emp2);
                    break;
            }
        }
    }
}

//创建HashTab
class HashTab {
    //创建员工链表数组,管理多条链表
    private EmpLinkedList[] empLinkedList;
    private int size; //表示有多少条链表
    //构造器
    public HashTab(int size) {
        this.size = size;
        //初始化empLinkedListArray
        empLinkedList = new EmpLinkedList[size];
        //初始化每个链表
        for(int i = 0; i < size; i++) {
            empLinkedList[i] = new EmpLinkedList();
        }
    }
    
    //添加雇员
    public void add(Emp emp) {
        //使用散列函数确定添加哪条链表
        int List_id = hashFun(emp.id);
        empLinkedList[List_id].add(emp);

    }
    
    //遍历所有的链表
    public void list() {
        for(int i = 0; i < size; i++) {
            empLinkedList[i].list(i);
        }
    }

    //根据输入的信息,查找员工
    public void findEmpById(Emp emp) {
        //使用散列函数确定到哪条链表查找
        int List_id = hashFun(emp.id);
        Emp emp_f = empLinkedList[List_id].findEmpById(emp);
        if(emp_f != null) {
            System.out.printf("第%d条链表,id=%d,name=%s\n", 			       	List_id+1,emp_f.id,emp_f.name);
        }else{
            System.out.println("在哈希表中,没有找到该员工");
        }
    }

    //根据输入信息删除员工
    public void del(Emp emp){
        int List_id = hashFun(emp.id);
        empLinkedList[List_id].del(emp);
    }
    //散列函数
    public int hashFun(int id) {
        //return id % size;   除法散列法
        //这里表示id为几就插入哪条链表
        return id-1;
    }
}


//创建EmpLinkedList链表
class EmpLinkedList {
    //头节点
    Emp head = new Emp(0,"",null);
    //添加员工
    public void add(Emp emp) {
        //定义移动节点,从头节点开始
        Emp curEmp = head;
        while(true) {
            //循环后移节点,找到链表末端跳出
            if(curEmp.next == null) {
                break;
            }
            curEmp = curEmp.next;
        }
        //此时curEmp为链表最后一个员工,将新员工赋值给curEmp的下个节点
        curEmp.next = emp;
    }

    //遍历链表的员工信息
    public void list(int no) {
        if(head.next==null) { //说明链表为空
            System.out.println("第 "+(no+1)+" 链表为空");
            return;
        }
        System.out.print("第 "+(no+1)+" 链表的信息为");
        //定义移动节点,头节点为空,从第二个节点开始
        Emp curEmp = head.next;  
        while(true) {
            System.out.printf(" => id=%d name=%s\t", curEmp.id, curEmp.name);
            if(curEmp.next == null) {//遍历到末端
                break;
            }
            curEmp = curEmp.next; //后移
        }
        System.out.println();
    }

    //根据id查找
    public Emp findEmpById(Emp emp) {
        //定义移动节点,从头节点开始
        Emp curEmp = head;
        while(true) {
            if(curEmp.name.equals(emp.name)) {//找到指定员工
                break;
            }
            if(curEmp.next == null) {//遍历当前链表没有找到该员工
                curEmp = null;
                break;
            }
            curEmp = curEmp.next;//后移
        }
        return curEmp;
    }

    public void del(Emp emp){
        //定义移动节点,从头节点开始
        Emp curEmp = head;
        while(true) {
            if (curEmp.next == null){
                System.out.println("找不到该员工");
                break;
            }
            //循环后移节点,找到待删除节点
            if(curEmp.next.name.equals(emp.name)) {
                //将待删除的节点替换为它的下一个节点
                curEmp.next = curEmp.next.next;
                break;
            }
            curEmp = curEmp.next;
        }
    }
}
//员工类
class Emp {
    public int list_id;
    public int id;
    public String name;
    public Emp next;
    public Emp(int id, String name,Emp next) {
        this.id = id;
        this.name = name;
        this.next = next;
    }
    public Emp(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

在这里插入图片描述

六.二叉树(Binary tree)

有序数组的优势在于二分查找,链表的优势在于数据的插入和删除。但是在有序数组中插入数据很慢,在链表中查找数据效率很低。综合以上情况,二叉树可以利用链表和有序数组的优势,同时可以合并有序数组和链表的优势

二叉树是n个有限元素的集合,由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树

存储方式有顺序存储、链式存储

public class main {
    public static void main(String[] args) {
        //创建二叉树,添加节点
        BinaryTree binaryTree = new BinaryTree();
        StudentNode root = new StudentNode(1, "AA");
        StudentNode node2 = new StudentNode(2, "BB");
        StudentNode node3 = new StudentNode(3, "CC");
        StudentNode node4 = new StudentNode(4, "DD");
        StudentNode node5 = new StudentNode(5, "EE");
        StudentNode node6 = new StudentNode(6, "FF");
        root.setLeft(node2);
        root.setRight(node3);
        node2.setLeft(node4);
        node3.setLeft(node5);
        node3.setRight(node6);
        //添加根节点
        binaryTree.setRoot(root);

		System.out.println("前序遍历"); // 1,2,4,3,5,6
		binaryTree.preOrder();

		System.out.println("中序遍历");
		binaryTree.infixOrder(); // 4,2,1,5,3,6

		System.out.println("后序遍历");
		binaryTree.postOrder(); // 4,2,5,6,3,1

        //前序遍历,查找5次
		System.out.println("前序遍历查找");
		StudentNode resNode1 = binaryTree.preOrderSearch(5);
		if (resNode1 != null) {
			System.out.printf("num=%d name=%s", resNode1.getNum(), resNode1.getName());
		} else {
			System.out.printf("没有找到%d号学生", 5);
		}

        //中序遍历,查找4次
		System.out.println("中序遍历查找");
        StudentNode resNode2 = binaryTree.infixOrderSearch(5);
        if (resNode2 != null) {
            System.out.printf("num=%d name=%s", resNode2.getNum(), resNode2.getName());
        } else {
            System.out.printf("没有找到%d号学生", 5);
        }

        //后序遍历,查找3次
		System.out.println("后序遍历查找");
		StudentNode resNode3 = binaryTree.postOrderSearch(5);
		if (resNode3 != null) {
			System.out.printf("num=%d name=%s", resNode3.getNum(), resNode3.getName());
		} else {
			System.out.printf("没有找到%d号学生", 5);
		}

        //删除结点
        System.out.println("删除前,前序遍历");
        binaryTree.preOrder(); //  1,2,4,3,5,6

        binaryTree.delNode(5);

        System.out.println("删除后,前序遍历");
        binaryTree.preOrder(); //1,2,4,3,6
    }
}

//定义BinaryTree二叉树
class BinaryTree {
    private StudentNode root;

    public void setRoot(StudentNode root) {
        this.root = root;
    }

    //删除结点
    public void delNode(int num) {
            root.delNode(num);
    }
    //前序遍历
    public void preOrder() {
        this.root.preOrder();
    }

    //中序遍历
    public void infixOrder() {
        this.root.infixOrder();
    }

    //后序遍历
    public void postOrder() {
        this.root.postOrder();
    }

    //前序遍历查找
    public StudentNode preOrderSearch(int num) {
        return root.preOrderSearch(num);
    }

    //中序遍历查找
    public StudentNode infixOrderSearch(int num) {
        return root.infixOrderSearch(num);
    }

    //后序遍历查找
    public StudentNode postOrderSearch(int num) {
        return this.root.postOrderSearch(num);
    }
}

//先创建StudentNode 结点
class StudentNode {
    private int num;
    private String name;
    private StudentNode left; //默认null
    private StudentNode right; //默认null
    public StudentNode(int num, String name) {
        this.num = num;
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

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

    public StudentNode getLeft() {
        return left;
    }

    public void setLeft(StudentNode left) {
        this.left = left;
    }

    public StudentNode getRight() {
        return right;
    }

    public void setRight(StudentNode right) {
        this.right = right;
    }

    @Override
    public String toString() {
        return "StudentNode{" +
                "num=" + num +
                ", name='" + name +
                '}';
    }

    //递归删除结点
    //如果删除的节点是叶子节点,则删除该节点
    //如果删除的节点是非叶子节点,则删除该子树
    public void delNode(int num) {
        //如果当前结点的左子结点不为空,并且左子结点 就是要删除结点,就将this.left = null; 并且就返回(结束递归删除)
        if(this.left != null && this.left.num == num) {
            this.left = null;
            return;
        }
        //如果当前结点的右子结点不为空,并且右子结点 就是要删除结点,就将this.right= null ;并且就返回(结束递归删除)
        if(this.right != null && this.right.num == num) {
            this.right = null;
            return;
        }
        //左子树递归删除
        if(this.left != null) {
            this.left.delNode(num);
        }
        //右子树递归删除
        if(this.right != null) {
            this.right.delNode(num);
        }
    }

    //前序遍历实现
    public void preOrder() {
        //输出父结点
        System.out.println(this);
        //递归向左子树前序遍历
        if(this.left != null) {
            this.left.preOrder();
        }
        //递归向右子树前序遍历
        if(this.right != null) {
            this.right.preOrder();
        }
    }

    //中序遍历实现
    public void infixOrder() {
        //递归向左子树中序遍历
        if(this.left != null) {
            this.left.infixOrder();
        }
        //输出父结点
        System.out.println(this);
        //递归向右子树中序遍历
        if(this.right != null) {
            this.right.infixOrder();
        }
    }

    //后序遍历实现
    public void postOrder() {
        //递归向右子树后序遍历
        if(this.left != null) {
            this.left.postOrder();
        }
        //递归向右子树后序遍历
        if(this.right != null) {
            this.right.postOrder();
        }
        //输出父结点
        System.out.println(this);
    }

    //前序遍历查找实现
    //前序遍历顺序:1,2,4,3,5,6
    //1开始,按照遍历顺序依次对比
    public StudentNode preOrderSearch(int num) {
        System.out.println("查找中......");
        //this表示当前节点(父节点),对比目标节点,是则返回this
        if(this.num == num) {
            return this;
        }
        StudentNode resNode = null;
        //遍历左子树
        if(this.left != null) {
            resNode = this.left.preOrderSearch(num);
        }
        if(resNode != null) {
            return resNode;
        }
        //遍历右子树
        if(this.right != null) {
            resNode = this.right.preOrderSearch(num);
        }
        return resNode;
    }

    //中序遍历查找
    //中序遍历顺序:4,2,1,5,3,6
    //1开始,找到4,按照遍历顺序依次对比
    public StudentNode infixOrderSearch(int num) {
        StudentNode resNode = null;
        //遍历左子树
        if(this.left != null) {
            resNode = this.left.infixOrderSearch(num);
        }
        if(resNode != null) {
            return resNode;
        }
        System.out.println("查找中......");
        //this表示当前节点(父节点),对比目标节点,是则返回this
        if(this.num == num) {
            return this;
        }
        //遍历右子树
        if(this.right != null) {
            resNode = this.right.infixOrderSearch(num);
        }
        return resNode;
    }

    //后序遍历查找
    //后序遍历顺序:4,2,5,6,3,1
    //1开始,找到4,按照遍历顺序依次对比
    public StudentNode postOrderSearch(int num) {
        StudentNode resNode = null;
        //遍历左子树
        if(this.left != null) {
            resNode = this.left.postOrderSearch(num);
        }
        if(resNode != null) {
            return resNode;
        }
        //遍历右子树
        if(this.right != null) {
            resNode = this.right.postOrderSearch(num);
        }
        if(resNode != null) {
            return resNode;
        }
        System.out.println("查找中......");
        //this表示当前节点(父节点),对比目标节点,是则返回this
        if(this.num == num) {
            return this;
        }
        return resNode;
    }
}

在这里插入图片描述

七.图(Graph)

图是由顶点的有穷非空集合和顶点之间边的集合组成, 通常表示为: G(V,E), 其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合

图形结构中,数据元素(顶点)之间具有任意关系,图中任意两个数据元素之间都可能相关

图可以用邻接矩阵或邻接表表示

public class main {
    public static void main(String[] args) {
        //顶点的个数
        int n = 8;
        //顶点值数组
        String Vertexs[] = {"A", "B", "C", "D", "E", "F", "G", "H"};
        //创建图对象
        Graph graph = new Graph(n);
        //循环添加顶点
        for(String vertex: Vertexs) {
            graph.insertVertex(vertex);
        }
        //定义各个边
        graph.insertEdge(0, 1, 1);
        graph.insertEdge(0, 2, 1);
        graph.insertEdge(1, 3, 1);
        graph.insertEdge(1, 4, 1);
        graph.insertEdge(3, 7, 1);
        graph.insertEdge(4, 7, 1);
        graph.insertEdge(2, 5, 1);
        graph.insertEdge(2, 6, 1);
        graph.insertEdge(5, 6, 1);

        //显示图基本信息
        graph.showGraph();
        
        System.out.println("深度优先:");
        graph.dfs(); // 1->2->4->8->5->3->6->7
		System.out.println();
        System.out.println("广度优先:");
        graph.bfs(); // 1->2->3->4->5->6->7->8
        System.out.println();
        
        //显示邻结矩阵
        graph.showEdges();
    }
}
//定义图的属性
class Graph{
    private ArrayList<String> vertexList; //存储顶点集合
    private int[][] edges; //存储图对应的邻结矩阵
    private int numOfEdges; //表示边的数目
    private boolean[] isVisited; //记录某个结点是否被访问

    //构造器
    public Graph(int n) {
        //初始化邻结矩阵和顶点集合
        edges = new int[n][n];
        vertexList = new ArrayList<String>(n);
        numOfEdges = 0;
    }

    //插入结点
    public void insertVertex(String vertex) {
        vertexList.add(vertex);
    }

    //添加边
    public void insertEdge(int v1, int v2, int weight) {
        //设置邻接矩阵值,可以直接两个相连的顶点weight为1
        edges[v1][v2] = weight;
        edges[v2][v1] = weight;
        //统计边数
        numOfEdges++;
    }

    //显示图的基本信息
    public void showGraph(){
        System.out.println("顶点总数:"+vertexList.size());
        System.out.println("边总数:"+numOfEdges);
    }

    //显示图对应的邻接矩阵
    public void showEdges() {
        System.out.println("邻接矩阵:");
        for(int[] hang : edges) {
            for (int lie : hang)
                System.out.printf("%d\t",lie);
            System.out.println();
        }
    }

    //返回结点i(下标)对应的数据
    public String getValueByIndex(int i) {
        return vertexList.get(i);
    }

    //深度优先遍历算法
    private void dfs(boolean[] isVisited, int i) {
        //首先我们访问该顶点,输出
        System.out.print(getValueByIndex(i) + "->");
        //将顶点设置为已经访问
        isVisited[i] = true;
        //查找顶点i的第一个邻接顶点w
        int w = getFirstNeighbor(i);
        while(w != -1) {//找到第一个邻接顶点w
            //如果w顶点未被访问,继续递归查找它的第一个邻接顶点
            if(!isVisited[w]) {
                dfs(isVisited, w);
            }
            //如果该顶点已经被访问过,将i,w传过去,查找i的第二个邻接顶点
            w = getNextNeighbor(i, w);
        }
    }

    //对dfs进行一个重载, 遍历我们所有的顶点,并进行dfs
    public void dfs() {
        isVisited = new boolean[vertexList.size()];
        //遍历所有的顶点,进行dfs[回溯]
        for(int i = 0; i < vertexList.size(); i++) {
            if(!isVisited[i]) {
                dfs(isVisited, i);
            }
        }
    }

    //广度优先遍历算法
    private void bfs(boolean[] isVisited, int i) {
        int u ; // 表示队列的头顶点对应下标
        int w ; // 邻接顶点w
        //队列,记录顶点访问的顺序
        LinkedList queue = new LinkedList();
        //访问顶点,输出顶点信息
        System.out.print(getValueByIndex(i) + "->");
        //标记为已访问
        isVisited[i] = true;
        //将顶点加入队列
        queue.addLast(i);

        while( !queue.isEmpty()) {
            //取出队列的头顶点下标
            u = (Integer)queue.removeFirst();
            //得到第一个邻接顶点的下标 w
            w = getFirstNeighbor(u);
            while(w != -1) {//找到第一个邻接顶点w
                //如果w顶点未访问
                if(!isVisited[w]) {
                    //输出
                    System.out.print(getValueByIndex(w) + "->");
                    //标记已经访问
                    isVisited[w] = true;
                    //入队
                    queue.addLast(w);
                }
                //以u为前驱点,找w后面的下一个邻接顶点
                w = getNextNeighbor(u, w);
            }
        }
    }
    //遍历所有的结点,都进行广度优先搜索
    public void bfs() {
        isVisited = new boolean[vertexList.size()];
        for(int i = 0; i < vertexList.size(); i++) {
            if(!isVisited[i]) {
                bfs(isVisited, i);
            }
        }
    }

    //获取顶点的第一个邻接顶点
    public int getFirstNeighbor(int v1) {
        for(int j = 0; j < vertexList.size(); j++) {
            if(edges[v1][j] > 0) {
                return j;
            }
        }
        return -1;
    }
    //根据前一个邻接顶点的下标来获取下一个邻接顶点
    public int getNextNeighbor(int v1, int v2) {
        for(int j = v2 + 1; j < vertexList.size(); j++) {
            if(edges[v1][j] > 0) {
                return j;
            }
        }
        return -1;
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值