数据结构总结

1.链表

t02单链表的基本操作

import org.junit.Test;

import java.util.Scanner;

public class t02单链表的基本操作 {
    Scanner scanner = new Scanner(System.in);
    @Test
    public  void ss() {

        System.out.println("请输入你要选择的功能");
        System.out.println("1:头插法创建");
        System.out.println("2:尾插法法创建");
        System.out.println("3:打印链表");
        System.out.println("4:添加链表");
        System.out.println("5:删除节点");
        System.out.print("6:修改节点");
        int select = scanner.nextInt();
        Node head = new Node();
        while (select !=0){
            switch (select){
                case 1:
                    head = createHead();
                    print(head);
                    break;
                case 2:
                    head = createTail();
                    print(head);
                    break;
                case 3:
                    print(head);
                    break;
                case 4:
                    head = insert(head);
                    print(head);
                    break;
                case 5:
                    head = delete(head);
                    print(head);
                    break;
                case 6:
                    update(head);
                    print(head);
                    break;
            }
            System.out.print("请输入你要选择的功能:");
            select = scanner.nextInt();
        }
        System.out.println("退出了……");

    }

    /**
     * 初始化链表,头插法
     * @return
     */
    private Node createHead(){
        //头插法
        Node head = new Node(),tempNode;
        int x;
        tempNode = head;
        System.out.print("创造节点,请输入:");
        while ((x = scanner.nextInt()) != -1){
            Node node = new Node(x);
            tempNode.next = node;
            tempNode = node;
            System.out.print("请继续输入:");
        }
        return head.next;
    }

    /**
     * 尾插法
     * @return
     */
    private Node createTail(){
        Node head = null;
        int x;
        System.out.print("创造节点,请输入:");
        while ((x = scanner.nextInt()) != -1){
            Node node = new Node(x);
            node.next = head;
            head = node;
            System.out.print("请继续输入:");
        }
        return head;
    }

    /**
     * 打印链表
     * @param head
     */
    private void print(Node head){
        while (head != null){
            System.out.println(head.value);
            head = head.next;
        }
    }

    private int getLength(Node head){
        int length = 0;
        while (head != null){
            length++;
            head = head.next;
        }
        return length;
    }

    /**
     * 指定某个位置,进行插入
     * @param head
     * @return
     */
    private Node insert(Node head){
        System.out.print("请输入位置");
        int pos = scanner.nextInt();
        System.out.print("请输入值");
        int value = scanner.nextInt();
        Node pre = head;
        for (int i = 1; i < pos-1; i++) {
            pre = pre.next;
        }
        Node node = new Node(value);
        if (pos == 1){
            node.next = head;
            head = node;
        }else if (pos > getLength(head)+1){
            System.out.println("输入有误!!请重新输入!");
            head = insert(head);
        }
        else {
            node.next = pre.next;
            pre.next = node;
        }
        return head;

    }

    private Node delete(Node head){
        System.out.println("请输入要删除的位置:");
        int pos = scanner.nextInt();
        if (pos < 1 || pos > getLength(head)){
            System.out.println("输出错误,请重新输入");
            delete(head);
        }
        Node pre = head;

        for (int i = 1; i < pos-1; i++) {
            pre = pre.next;
        }
        if (pos == 1){
            return head.next;
        }else if (pos == getLength(head)){
            pre.next = null;
        } else {
            pre.next = pre.next.next;
        }
        return head;
    }

    private Node update(Node head){
        System.out.print("请输入要修改的位置:");
        int pos = scanner.nextInt();
        if (pos < 1 || pos > getLength(head)){
            System.out.print("输出错误,请重新输入");
            update(head);
        }
        System.out.print("请输入要修改的值:");
        int value = scanner.nextInt();
        Node cur = head;
        for (int i = 1; i < pos; i++) {
            cur = cur.next;
        }
        cur.value = value;
        return head;
    }


    class Node {
        int value;
        Node next;

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

        public Node() {
        }
    }
}

t04双向链表的基本操作

import org.junit.Test;

import java.util.Scanner;

import static java.lang.reflect.Array.getLength;

public class t04双向链表的基本操作 {

    private class Node {
        int value;
        Node next;
        Node pre;

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

        public Node() {
        }
    }
    Scanner scanner = new Scanner(System.in);
    @Test
    public void test(){
        System.out.println("请输入你要选择的功能");
        System.out.println("1:创建");
        System.out.println("2:打印链表");
        System.out.println("3:添加链表");
        System.out.println("4:删除节点");
        System.out.print("5:修改节点");
        int select = scanner.nextInt();
        Node head = new Node();
        while (select !=0){
            switch (select){
                case 1:
                    head = create();
                    print(head);
                    break;
                case 2:
                    print(head);
                    break;
                case 3:
                    head = insert(head);
                    print(head);
                    break;
                case 4:
                    head = delete(head);
                    print(head);
                    break;
                case 5:
                    head = update(head);
                    print(head);
                    break;
            }
            System.out.print("请输入你要选择的功能:");
            select = scanner.nextInt();
        }
        System.out.println("退出了……");
    }

    private Node update(Node head) {
        System.out.print("指定位置:");
        int pos = scanner.nextInt();
        if (pos < 1 || pos > getLength(head)){
            System.out.println("位置不对路……请重新输入");
            update(head);
        }else {
            System.out.print("指定值:");
            int value = scanner.nextInt();
            Node cur = head;
            for (int i = 1; i < pos; i++) {
                cur = cur.next;
            }
            cur.value = value;
        }
        return head;
    }

    /**
     * 删除
     * @param head
     * @return
     */
    private Node delete(Node head) {
        System.out.print("指定位置:");
        int pos = scanner.nextInt();
        if (pos < 1 || pos > getLength(head)){
            System.out.println("位置不对路……请重新输入");
            delete(head);
        }else {
            if (pos == 1){
                return head.next;
            }

            Node cur = head;
            for (int i = 1; i < pos; i++) {
                cur = cur.next;
            }
            cur.pre.next = cur.next;
            if (cur.next != null){
                cur.next.pre = cur.pre;
            }
        }
        return head;
    }

    /**
     * 插入
     * @param head
     * @return
     */
    private Node insert(Node head) {
        System.out.print("指定位置:");
        int pos = scanner.nextInt();
        if (pos < 1 || pos > getLength(head)){
            System.out.println("位置不对路……请重新输入");
            insert(head);
        }else {
            System.out.print("指定值:");
            int value = scanner.nextInt();
            Node node = new Node(value);
            if (pos == 1){
                node.next = head;
                head.pre = node;
                head = node;
            }else {
                Node pre = head;
                for (int i = 1; i < pos-1; i++) {
                    pre = pre.next;
                }
                node.next = pre.next;
                pre.next = node;
                node.pre = pre;
            }
        }
        return head;
    }

    private int getLength(Node head){
        int length = 0;
        while (head != null){
            length++;
            head = head.next;
        }
        return length;
    }

    /**
     * 创建
     * @return
     */
    private Node create(){
        int value;
       Node head = new Node(),cur = null;
        System.out.print("请输入值:");
        int flag = 1;
        while ((value = scanner.nextInt()) != -1){
            if (flag == 1){
                head.value = value;
                cur = head;
                flag = 0;
            }else {
                Node node = new Node(value);
                cur.next = node;
                node.pre = cur;
                cur = node;
            }
            System.out.print("请继续输入:");
        }
        return head;
    }

    /**
     * 打印
     * @param head
     */
    private void print(Node head){
        while (head != null){
            System.out.println(head.value);
            head = head.next;
        }
    }
}

t06循环链表的基本操作


import org.junit.Test;

import java.util.Scanner;


public class t06循环链表的基本操作 {
    private class Node {
        int value;
        Node next;
        Node pre;

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

        public Node() {
        }
    }

    Scanner scanner = new Scanner(System.in);

    @Test
    public void main() {
        System.out.println("请输入你要选择的功能");
        System.out.println("1:创建");
        System.out.println("2:打印链表");
        System.out.println("3:添加链表");
        System.out.println("4:删除节点");
        System.out.print("5:修改节点");
        int select = scanner.nextInt();
        Node head = new Node();
        while (select != 0) {
            switch (select) {
                case 1:
                    head = create();
                    print(head);
                    break;
                case 2:
                    print(head);
                    break;
                case 3:
                    head = insert(head);
                    print(head);
                    break;
                case 4:
                    head = delete(head);
                    print(head);
                    break;
                case 5:
                    head = update(head);
                    print(head);
                    break;
            }
            System.out.print("请输入你要选择的功能:");
            select = scanner.nextInt();
        }
        System.out.println("退出了……");
    }

    private Node update(Node head) {
        System.out.print("指定位置:");
        int pos = scanner.nextInt();
        if (pos < 1 || pos > getLength(head)){
            System.out.println("位置不对路……请重新输入");
            update(head);
        }else {
            System.out.print("指定值:");
            int value = scanner.nextInt();
            Node cur = head;
            for (int i = 1; i < pos; i++) {
                cur = cur.next;
            }
            cur.value = value;
        }
        return head;
    }

    private Node delete(Node head) {
        System.out.print("指定位置:");
        int pos = scanner.nextInt();
        if (pos < 1 || pos > getLength(head)){
            System.out.println("位置不对路……请重新输入");
            delete(head);
        }else {
            Node cur = head.next;
            if (pos == 1){
                head.pre.next = cur;
                return cur;
            }
            cur = head;
            for (int i = 1; i < pos; i++) {
                cur = cur.next;
            }
            cur.pre.next = cur.next;
            cur.next.pre = cur.pre;
        }
        return head;
    }

    private Node insert(Node head) {
        System.out.print("指定位置:");
        int pos = scanner.nextInt();
        if (pos < 1 || pos > getLength(head)) {
            System.out.println("位置不对路……请重新输入");
            insert(head);
        } else {
            System.out.print("指定值:");
            int value = scanner.nextInt();
            Node node = new Node(value);
            if (pos == 1) {
                node.next = head;
                node.pre = head.pre;
                head.pre.next = node;
                head.pre = node;
                head = node;
            } else {
                Node pre = head;
                for (int i = 1; i < pos - 1; i++) {
                    pre = pre.next;
                }
                    node.next = pre.next;
                    pre.next = node;
                    node.pre = pre;
            }
        }

        return head;
    }

    private Node create() {
        System.out.print("请输入值:");
        Node head = new Node();
        Node pre = head;
        int value = 0;
        int flag = 0;
        while ((value = scanner.nextInt()) != -1) {
            if (flag == 0) {
                head.value = value;
                head.next = head;
                head.pre = head;
                flag++;
            } else {
                Node node = new Node();
                node.value = value;
                pre.next = node;
                node.pre = pre;
                node.next = head;
                pre = node;
                head.pre = node;
            }

            System.out.print("请继续输入值:");
        }
        return head;
    }

    private void print(Node head) {
        Node cur = head;
        while (cur.next != head) {
            System.out.println(cur.value);
            cur = cur.next;
        }
        System.out.println(cur.value);
    }

    private int getLength(Node head) {
        int length = 0;
        Node cur = head;
        while (cur.next != head) {
            cur = cur.next;
            length++;
        }

        return ++length;
    }
}

2.栈

t01链表栈

    /**
     * ;链表本质上是头插法
     */
    private class Node {
        int value;
        Node next;


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

        public Node(int value, Node next) {
            this.value = value;
            this.next = next;
        }

        public Node() {
        }
    }

    private class Stack {
        Node top;
        int count;
        int size = 5;

        public Stack() {

        }

        /**
         * 入栈
         *
         * @return
         */
        public void pull(int value) {
            if (isFull()) {
                throw new RuntimeException("栈满了");
            }
            top = new Node(value, top);
            this.count++;

        }

        public boolean isFull() {
            if (this.count == this.size) {
                return true;
            } else {
                return false;
            }
        }

        public boolean isEmpy() {
            if (this.count == 0) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * 出栈
         *
         * @return
         */
        public int push() {
            if (isEmpy()) {
                throw new RuntimeException("栈为空");
            }
            int value = this.top.value;
            this.top = this.top.next;
            this.count--;
            return value;
        }

        public int peek() {
            if (isEmpy()) {
                throw new RuntimeException("栈为空");
            }
            int value = this.top.value;
            return value;
        }

        public void print(){
            if (isEmpy()) System.out.println("无");
            else {
                while (!isEmpy()){
                    System.out.println(this.push());
                }
            }
        }


    }


    @Test
    public void test() {
        Stack stack = new Stack();
        stack.pull(1);
        stack.pull(2);
        stack.pull(3);
        stack.pull(4);
        stack.pull(5);
        stack.pull(6);
        stack.print();

    }

t02数组栈

   private class Stack{
        private int[] arr;
        private int size = 5;
        private int count;
        public Stack(){
            this.arr = new int[size];
            this.count = -1;
        }

        public boolean isFull(){
            if (this.count == this.size-1) return true;
            else return false;
        }

        public boolean isEmpty(){
            if (count == -1) return true;
            else return false;
        }

        public void push(int value){
            if (isFull()) throw new RuntimeException("栈满了");
            arr[++count] = value;
        }

        public int pull(){
            if (isEmpty()) throw new RuntimeException("空");
            return arr[count--];
        }

        public int peek(){
            if (isEmpty()) throw new RuntimeException("空");
            return arr[count];
        }
        public void print(){
            if (isEmpty()) System.out.println("无");
            else {
                while (!isEmpty()) System.out.println(pull());;
            }
        }
    }

    @Test
    public void test(){
        Stack stack = new Stack();
        stack.push(1);
//        System.out.println(stack.peek());
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);
//        stack.push(6);
//
        stack.print();
    }

3.队列

t01链表队列的实现

    /**
     * 队列本质上是尾插法
     *
     */
    private class Node {
        int value;
        Node next;
        public Node(int value) {
            this.value = value;
        }

        public Node(int value, Node next) {
            this.value = value;
            this.next = next;
        }

        public Node() {
        }
    }

    private class Queue{
        Node tail;
        Node head;
        int size = 5;
        int count = 0;

        private boolean isEmpty(){
            if (this.head == null) return true;
            else return false;
        }

        private boolean isFull(){
            if (size == count) return true;
            else return false;
        }


        private void push(int value) {
            if (head == null){
                head = new Node(value);
                tail = head;
            }else {
                if (isFull()) throw new RuntimeException("队列满");
                else {
                    Node temp = new Node(value);
                    tail.next = temp;
                    tail = temp;
                }
            }
            count++;
        }


        private int  pull(){
            if (isEmpty()) throw new RuntimeException("队列空");
            int value = head.value;
            head = head.next;
            count--;
            return value;
        }



        private int  peek(){
            if (isEmpty()) throw new RuntimeException("队列空");
            int value = head.value;
            return value;
        }

        private void print(){
            while (this.head != null){
                System.out.println(pull());
            }
        }



    }

    @Test
    public void test(){
        Queue queue = new Queue();
        queue.push(1);
        queue.push(2);
        queue.push(3);
        queue.push(4);
        queue.push(5);
        queue.pull();
        queue.push(6);


        queue.print();
//        System.out.println(queue.push());

//        System.out.println(queue.push());
    }

t02数组队列的实现

    private class Queue{
        private int size = 5;
        private int count = 0;
        private int head = -1;
        private int tail = -1;
        int[] arr;
        public Queue(){
            arr = new int[size];
        }

        private boolean isEmpty(){
            if (this.count == 0) return true;
            else return false;
        }

        private boolean isFull(){
            if (head == tail && head !=-1) return true;
            else return false;
        }

        private void pull(int value){
            if (isFull()) throw new RuntimeException("队列满");
            else {
                tail = (tail+1)%size;
                arr[tail] = value;
                count++;
            }
        }

        private int push(){
            if (isEmpty()) throw new RuntimeException("队列空");
            else {
                head = (head+1)%size;
                int value = arr[head];

                count--;
                return value;
            }

        }

        private int peek(){
            if (isEmpty()) throw new RuntimeException("队列空");
            return arr[count];
        }

        private void print(){
            if (isEmpty()) throw new RuntimeException("队列空");
            while (!isEmpty()){
                System.out.println(push());
            }
        }
    }

    @Test
    public void test(){
        Queue queue = new Queue();
        queue.pull(1);
        queue.pull(2);
        queue.pull(3);
        queue.pull(4);
        queue.pull(5);
        queue.push();
        queue.pull(6);
        queue.print();
    }

3.树

T01二叉树

import org.junit.Test;

import java.util.*;

public class T01二叉树 {
    private class Node {
        private int value;
        private Node left;
        private Node right;

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

        public Node() {
        }

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        public Node getLeft() {
            return left;
        }

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

        public Node getRight() {
            return right;
        }

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

    private class BinaryTree {
        private Node root;

        //清空节点
        private void clear(Node node) {
            if (node != null) {
                clear(node.left);
                clear(node.right);
                node = null;
            }
        }

        //判断树是否为空
        private boolean isEmpty() {
            return root == null;
        }

        //获取树的高度
        private int getHeight(Node node) {
            if (node == null) {
                return 0;
            } else {
                //获取左子树高度
                int l = getHeight(root.left);
                //获取右子树高度
                int r = getHeight(root.right);
                return l > r ? (l + 1) : (r + 1);
            }
        }

        private int getHeight() {
            return getHeight(root);
        }

        //获取节点数
        private int getSize(Node node) {
            if (node == null) {
                return 0;
            } else {
                return getSize(node.left) + getSize(node.right) + 1;
            }
        }

        private int getSize() {
            return getSize(root);
        }

        //得到某个节点的父节点
        private Node getParent(Node pre, Node node) {
            if (pre == null) return null;
            //是node的父节点的筛选条件
            if (pre.left == node || pre.right == node) return pre;
            Node temp = null;
            if (getParent(pre.left, node) != null) {
                //遍历下一个左子树,不为空,就直接返回,为空,就开始遍历下个右子树
                temp = getParent(pre.left, node);
                return temp;
            } else {
                return getParent(pre.right, node);
            }
        }

        //给某个节点插入左节点
        private void insertLeft(Node parent, Node node) {
            parent.setLeft(node);
        }

        //给某个节点插入右节点
        private void insertRight(Node parent, Node node) {
            parent.setRight(node);
        }

        //先序遍历
        private void preOrder(Node node) {
            if (node != null) {
                //输出根节点的值
                System.out.println("/" + node.value + "\\");
                //遍历走节点
                preOrder(node.left);
                //走节点遍历完后,再遍历右节点
                preOrder(node.right);
            }
        }

        private void preOrder() {
            preOrder(root);
        }

        private void centerOrder() {
            centerOrder(root);
        }

        private void postOrder() {
            postOrder(root);
        }

        //中序遍历
        private void centerOrder(Node node) {
            if (node != null) {
                //先一直遍历左节点
                centerOrder(node.left);
                //遍历完左节点,打印值
                System.out.println(node.value);
                //打印值后,在遍历右节点
                centerOrder(node.right);
            }
        }

        //后序遍历
        private void postOrder(Node node) {
            if (node != null) {
                //先一直遍历左节点
                centerOrder(node.left);
                //遍历完左节点,再遍历右节点
                centerOrder(node.right);
                //遍历完节点,打印值
                System.out.println(node.value);
            }
        }

        private void insert(int value) {
            Node node = new Node(value);
            if (root == null) {
                //第一次
                root = node;
            } else {
                //第二次
                Node temp = this.root;
                while (temp != null) {
                    if (value < temp.value) {
                        //小于就进入左节点
                        if (temp.left == null) {
                            //为空就添加
                            temp.left = node;
                            return;
                        } else {
                            //继续往下搜索
                            temp = temp.left;
                        }
                    } else {
                        //大于就进入又节点
                        if (temp.right == null) {
                            //为空就添加
                            temp.right = node;
                            return;
                        } else {
                            //继续往下搜索
                            temp = temp.right;
                        }
                    }
                }
            }
        }

        private void insert2(int value) {
            Node node = new Node(value);
            if (root == null) {
                //第一次
                root = node;
            } else {
                //第二次
                Node temp = this.root;
                while (temp != null) {

                    //小于就进入左节点
                    if (temp.left == null) {
                        //为空就添加
                        temp.left = node;
                        return;
                    } else if (temp.right == null) {
                        //为空就添加
                        temp.right = node;
                        return;
                    } else if (temp.left.left == null || temp.left.right == null) {
                        temp = temp.left;
                    } else if (temp.right.left == null || temp.right.right == null) {
                        temp = temp.right;
                    }
                }
            }
        }
    }


    /**
     * 深度遍历,本质上是个前序遍历
     * @param root
     * @return
     */
    private ArrayList<Integer> dfs(Node root) {
        ArrayList<Integer> lists = new ArrayList<>();
        if (root == null) return lists;
        Stack<Node> stack = new Stack<>();
        stack.push(root);
        //只要栈不是空的
        while (!stack.isEmpty()) {
            //弹出元素
            Node pop = stack.pop();
            //当前节点的右节点不为空时,就一直加入
            if (pop.right != null)
                //加入右节点
                stack.push(pop.right);
            if (pop.left != null)
                //加入左节点
                stack.push(pop.left);
            //当为叶子节点时就加入
            lists.add(pop.value);
        }
        return lists;
    }

    private ArrayList<Integer> bfs(Node node){
        ArrayList<Integer> lists = new ArrayList<>();
        if (node == null) return lists;
        LinkedList<Node> queue = new LinkedList<>();
        //加入头节点
        queue.offer(node);
        while (!queue.isEmpty()){
            Node poll = queue.poll();
            //不为空就添加
            if (poll.left != null) queue.offer(poll.left);
            if (poll.right != null) queue.offer(poll.right);
            lists.add(poll.value);
        }
        return lists;
    }

    @Test
    public void test() {
        BinaryTree binaryTree = new BinaryTree();
        binaryTree.insert2(10);
        binaryTree.insert2(12);
        binaryTree.insert2(2);
        binaryTree.insert2(3);
        binaryTree.insert2(5);
//        binaryTree.preOrder();
//        ArrayList<Integer> dfs = dfs(binaryTree.root);
        ArrayList<Integer> bfs = bfs(binaryTree.root);
        System.out.println(bfs.toString());

    }
}

4.图

T01图的存储

public class T01图的存储 {
    /**
     * 邻接矩阵
     */
    private class MatrixUDG {

        private char[] mVexs;       // 顶点集合
        private int[][] mMatrix;    // 邻接矩阵

        /*
         * 创建图(自己输入数据)
         */
        public MatrixUDG() {

            // 输入"顶点数"和"边数"
            System.out.printf("input vertex number: ");
            int vlen = readInt();
            System.out.printf("input edge number: ");
            int elen = readInt();
            if (vlen < 1 || elen < 1 || (elen > (vlen * (vlen - 1)))) {
                System.out.printf("input error: invalid parameters!\n");
                return;
            }

            // 初始化"顶点"
            mVexs = new char[vlen];
            for (int i = 0; i < mVexs.length; i++) {
                System.out.printf("vertex(%d): ", i);
                mVexs[i] = readChar();
            }

            // 初始化"边"
            mMatrix = new int[vlen][vlen];
            for (int i = 0; i < elen; i++) {
                // 读取边的起始顶点和结束顶点
                System.out.printf("edge(%d):", i);
                char c1 = readChar();
                char c2 = readChar();
                int p1 = getPosition(c1);
                int p2 = getPosition(c2);

                if (p1 == -1 || p2 == -1) {
                    System.out.printf("input error: invalid edge!\n");
                    return;
                }

                mMatrix[p1][p2] = 1;
                mMatrix[p2][p1] = 1;
            }
        }

        /*
         * 创建图(用已提供的矩阵)
         *
         * 参数说明:
         *     vexs  -- 顶点数组
         *     edges -- 边数组
         */
        public MatrixUDG(char[] vexs, char[][] edges) {

            // 初始化"顶点数"和"边数"
            int vlen = vexs.length;
            int elen = edges.length;

            // 初始化"顶点"
            mVexs = new char[vlen];
            for (int i = 0; i < mVexs.length; i++)
                mVexs[i] = vexs[i];

            // 初始化"边"
            mMatrix = new int[vlen][vlen];
            for (int i = 0; i < elen; i++) {
                // 读取边的起始顶点和结束顶点
                int p1 = getPosition(edges[i][0]);
                int p2 = getPosition(edges[i][1]);

                mMatrix[p1][p2] = 1;
                mMatrix[p2][p1] = 1;
            }
        }

        /*
         * 返回ch位置
         */
        private int getPosition(char ch) {
            for (int i = 0; i < mVexs.length; i++)
                if (mVexs[i] == ch)
                    return i;
            return -1;
        }

        /*
         * 读取一个输入字符
         */
        private char readChar() {
            char ch = '0';

            do {
                try {
                    ch = (char) System.in.read();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } while (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')));

            return ch;
        }

        /*
         * 读取一个输入字符
         */
        private int readInt() {
            Scanner scanner = new Scanner(System.in);
            return scanner.nextInt();
        }

        /*
         * 打印矩阵队列图
         */
        public void print() {
            System.out.printf("Martix Graph:\n");
            for (int i = 0; i < mVexs.length; i++) {
                for (int j = 0; j < mVexs.length; j++)
                    System.out.printf("%d ", mMatrix[i][j]);
                System.out.printf("\n");
            }
        }


    }


    @Test
    public void test01() {
        char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        char[][] edges = new char[][]{
                {'A', 'C'},
                {'A', 'D'},
                {'A', 'F'},
                {'B', 'C'},
                {'C', 'D'},
                {'E', 'G'},
                {'F', 'G'}};
        MatrixUDG pG;

        /**a b c d e f g
         * 0 0 1 1 0 1 0
         * 0 0 1 0 0 0 0
         * 1 1 0 1 0 0 0
         * 1 0 1 0 0 0 0
         * 0 0 0 0 0 0 1
         * 1 0 0 0 0 0 1
         * 0 0 0 0 1 1 0
         */
        // 自定义"图"(输入矩阵队列)
        //pG = new MatrixUDG();
        // 采用已有的"图"
        pG = new MatrixUDG(vexs, edges);

        pG.print();   // 打印图
    }

    @Test
    public void test02() {
        MatrixUDG matrixUDG = new MatrixUDG();
        matrixUDG.print();
    }

    @Test
    public void test03() {
        int x, y;//输入的两条边
        int v, e;//顶点数和边数
        Scanner scanner = new Scanner(System.in);
        System.out.print("顶点数:");
        v = scanner.nextInt();
        System.out.print("边数:");
        e = scanner.nextInt();
        int[][] arr = new int[v][v];
        for (int i = 0; i < e; i++) {
            System.out.print("边端点x(" + i + ")");
            x = scanner.nextInt();
            System.out.print("边端点y(" + i + ")");
            y = scanner.nextInt();
            arr[x - 1][y - 1] = 1;
            arr[y - 1][x - 1] = 1;
        }
        System.out.println();
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }


    /**
     * 邻接表
     */
    //有向图
    private class Edge {
        private int v; //边的起点
        private int w; //边的终点

        public Edge(int v, int w) {
            this.v = v;
            this.w = w;
        }

        public int from() {
            return v;
        }

        public int to() {
            return w;
        }

        @Override
        public String toString() {
            return String.format("%d->%d", v, w);
        }


    }

    private class EdgeWeightDigraph {
        public int v;//顶点的个数
        public int e; //边的个数

        public ArrayList<Edge>[] adj; //邻接表

        public EdgeWeightDigraph(int v) {
            this.v = v;
            this.e = e;
            adj = new ArrayList[v];
            for (int i = 0; i < v; i++) {
                adj[i] = new ArrayList<Edge>();
            }
        }

        /**
         * 添加边(有向)
         *
         * @param e
         */
        public void addEdge(Edge e) {
            adj[e.from()].add(e);
            this.e++;
        }

        /**
         * 添加变 无向
         *
         * @param e
         */
        public void addEdge2(Edge e) {
            adj[e.from()].add(e);
            int from = e.from();
            int to = e.to();
            Edge edge = new Edge(to, from);
            adj[edge.from()].add(edge);
            this.e++;
        }

        public void printEdge() {
            for (int i = 0; i < v; i++) {
                for (int j = 0; j < adj[i].size(); j++) {
                    Edge e = adj[i].get(j);
                    if (j == 0) System.out.print(e);
                    else System.out.print("->" + e.to());
                }
                System.out.println();
            }
        }


        public void printEdge2() {
            for (int i = 0; i < v; i++) {
                for (int j = 0; j < adj[i].size(); j++) {
                    Edge e = adj[i].get(j);
                    if (j == 0) System.out.print(e);
                    else System.out.print("->" + e.to());
                }
                System.out.println();
            }
        }

    }

    @Test
    public void test04() {

        EdgeWeightDigraph graph = new EdgeWeightDigraph(5);

        Edge e = new Edge(0, 1);
        Edge e1 = new Edge(0, 2);
        Edge e11 = new Edge(0, 3);
        Edge e2 = new Edge(1, 2);
        Edge e3 = new Edge(2, 3);
        Edge e4 = new Edge(3, 4);

//        graph.addEdge(e);
//        graph.addEdge(e1);
//        graph.addEdge(e11);
//        graph.addEdge(e2);
//        graph.addEdge(e3);
//        graph.addEdge(e4);

        graph.addEdge2(e);
        graph.addEdge2(e1);
        graph.addEdge2(e11);
        graph.addEdge2(e2);
        graph.addEdge2(e3);
        graph.addEdge2(e4);
        graph.printEdge();

    }

    /**
     * 链式前向星
     */
    private class ChainForwardStar {

        private Edge[] edges;//边集数组,存放所有的边
        private int cnt = 0; //记录边的下标,比如,如果边的编号从零开始,
        // 那么第1条边的下标就是0,也就是edges的下标
        private int[] head;//头结点数组,里面存着的实际上是从某个节点出发,最近访问边数组的下标

        //    建立边集
        private class Edge {
            int to;
            int w;
            int next;
        }


        public void add(int u, int v, int w) {
            edges[cnt] = new Edge();//创建一条边将其放入边集数组
            edges[cnt].to = v;
            edges[cnt].w = w;
            //把当前边的下一个指向head最近访问的边,u代表着的是从那个节点出发的下标
            edges[cnt].next = head[u];
            //然后这条新建的边付给head,这样它就成为head最近访问的边
            //即以节点u出发的的边,最近访问的是新建的边
            head[u] = cnt;
            cnt++;
        }

        public void bfs(int node_num) {
            boolean[] visited = new boolean[node_num + 1];
            Queue<Integer> queue = new LinkedList<>();
            queue.offer(1);
            while (!queue.isEmpty()) {
                int u = queue.poll();
                System.out.print(u + " ");
                for (int i = head[u]; i != -1; i = edges[i].next) {
                    int f = edges[i].to;
                    if (!visited[f]) {
                        queue.offer(f);
                        visited[f] = true;
                    }
                }
            }
        }
    }

    @Test
    public void test05() {
        ChainForwardStar cc = new ChainForwardStar();
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入节点个数:");
        int node_num = scanner.nextInt();
        cc.head = new int[node_num + 1];
        for (int i = 0; i < cc.head.length; i++) {
            cc.head[i] = -1;
        }
        System.out.print("请输入边的数量:");
        int edge_num = scanner.nextInt();
        cc.edges = new ChainForwardStar.Edge[edge_num];
        System.out.print("请输入所有边,及他们的权重:格式: from to weight:(回车下一行开始)");
        //这两个输入的目的在于去掉回着符号
        scanner.nextLine();
        scanner.nextLine();
//        建图
        for (int i = 0; i < edge_num; i++) {
            String line = scanner.nextLine();
            String[] values = line.split(" ");
            int u = Integer.valueOf(values[0]);
            int v = Integer.valueOf(values[1]);
            int w = Integer.valueOf(values[2]);
            cc.add(u, v, w);
        }
//        遍历某个节点的邻接点
        System.out.print("请输入想要遍历的结点:");
        int node = scanner.nextInt();
        //cc.head[node],取出那个结点,它所只要有连接的边,就会继续循环
        int count = 1;
        for (int u =  cc.head[node]; u != -1; u =  cc.edges[u].next) {
            System.out.println(node+"结点连接的第" + count + "条边的去往结点->" +  cc.edges[u].to);
            System.out.println(node+"结点连接的第" + count + "条边的的权重" +  cc.edges[u].w);
            if (u == -1) {
                break;
            }
            count++;
            System.out.println(node + "号结点上出发的下一条边的下标:" +  cc.edges[u].next);
        }
//        输出访问结点的顺序
        cc.bfs(node_num);
    }
}

T02图的遍历

public class T02遍历 {

    private class BFSTest {

        /**
         * 队列
         */
        private Queue<Vertex> queue;
        /**
         * 邻接矩阵,0表示无边,1表示有边
         */
        private int[][] edges;
        /**
         * 顶点
         */
        private Vertex[] vertices;

        /**
         * 顶点个数
         *
         */
        private int size;

        /**
         * 初始化
         */
        public BFSTest(Vertex[] vertices, int[][] edges) {
            queue = new LinkedList<>();
            this.size = vertices.length;
            this.vertices = vertices;
            this.edges = edges;
        }

        public BFSTest() {
        }

        /**
         * BFS方法
         */
        public void BFS() {
            //向队列加入第一个顶点
            queue.offer(vertices[0]);
            //标记第一个顶点已经被访问
            vertices[0].wasVisited = true;
            //当队列不空
            while (!queue.isEmpty()) {
                //从队列中弹出并返回顶点
                Vertex item = queue.poll();
                System.out.println(item);

                int index = 0;
                //获取顶点所在的vertices数组的下标
                if (item != null) {//这样设计避免了for循环
                    index = item.index;
                }
                //size代表结点的个数
                //将与item相连的(即在item所在的行且邻接矩阵中值非0的)且未被访问的顶点加入到队列中
                for (int i = 0; i < size; i++) {
                    if ((edges[index][i] != 0) && (vertices[i].wasVisited == false)) {
                        queue.offer(vertices[i]);
                        vertices[i].wasVisited = true;
                    }
                }
            }
        }


        /**
         * 顶点类
         */
        private class Vertex {
            /**
             * 顶点值
             */
            private char vertex;
            /**
             * 第index个顶点(从0开始),这么设计避免了for循环
             */
            private int index;
            /**
             * 顶点是否被访问
             */
            private boolean wasVisited;

            public Vertex(char vertex, int index) {
                this.vertex = vertex;
                this.index = index;
                wasVisited = false;
            }

            @Override
            public String toString() {
                return "Vertex{" +
                        "vertex=" + vertex +
                        '}';
            }
        }
    }

    @Test
    public void test01() {
        BFSTest bfsTest = new BFSTest();
        //建立顶点集合 一共9个结点
        BFSTest.Vertex[] V = {
                bfsTest.new Vertex('0', 0),
                bfsTest.new Vertex('1', 1),
                bfsTest.new Vertex('2', 2),
                bfsTest.new Vertex('3', 3),
                bfsTest.new Vertex('4', 4),
                bfsTest.new Vertex('5', 5),
                bfsTest.new Vertex('6', 6),
                bfsTest.new Vertex('7', 7),
                bfsTest.new Vertex('8', 8)
        };
        int[][] edges = {
                {0, 1, 1, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 1, 1, 0, 0, 0, 0},
                {0, 0, 0, 0, 1, 1, 1, 0, 0},
                {0, 0, 0, 0, 1, 0, 0, 0, 0},
                {0, 1, 0, 0, 0, 0, 0, 1, 0},
                {0, 0, 0, 0, 0, 0, 1, 0, 0},
                {0, 0, 1, 0, 0, 0, 0, 0, 1},
                {0, 0, 0, 0, 0, 1, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0},
        };
        BFSTest b = new BFSTest(V, edges);
        b.BFS();
    }

    private class DFSTest {

        /**
         * 栈
         */
        private Stack<Vertex> stack;
        /**
         * 邻接矩阵,0表示无边,1表示有边
         */
        private int[][] edges;
        /**
         * 顶点
         */
        private Vertex[] vertices;

        /**
         * 顶点个数
         */
        private int size;
        /**
         * 初始化
         */
        public DFSTest(Vertex[] vertices, int[][] edges){
            stack=new Stack<>();
            this.size=vertices.length;
            this.vertices=vertices;
            this.edges=edges;
        }

        public DFSTest(){}

        /**
         * DFS方法
         */
        public void DFS(){
            //输出第一个顶点
            System.out.println(vertices[0]);
            //将第一个顶点压栈
            stack.push(vertices[0]);
            //标记已经被访问过
            vertices[0].wasVisited=true;
            //栈顶顶点
            Vertex item;
            //栈顶顶点所在的行
            int row;
            //需要回溯到某一行的某一列(避免每次都从第1列扫描每行,作为优化)
            int column=0;
            //当栈不空
            while (!stack.isEmpty()){
                item=stack.peek();
                row=item.index;
                column=isExistAdjacentPoint(row,column);
                //判断栈顶元素是否存在未被访问过的邻接点
                if(column == -1){//不存在
                    stack.pop();
                    //回溯到上一行的下一列,例如当前在2号顶点,2号顶点是从(6,2)过来的,
                    // 2号顶点已经遍历完了,发现没有满足条件的邻接点,那么下次就会遍历 (6,3),
                    // 避免了从(6,0)开始遍历,这段代码利用了邻接矩阵中行与列的关系
                    column=row+1;
                }else {//存在
                    System.out.println(vertices[column]);
                    vertices[column].wasVisited=true;
                    stack.push(vertices[column]);
                    //下一次从第一列开始遍历,例如(1,3)满足条件,
                    // 那么下次会从(3,0)开始遍历寻找与3相邻的邻接点
                    column=0;
                }

            }
        }

        /**
         * 判断是否存在邻接点
         * @param row 当前顶点所在的行号
         * @param column  当前顶点所在的行的所有列
         * @return 下标,若不存在,则返回-1
         */
        private int isExistAdjacentPoint(int row, int column) {
            for(int i=column;i<size;i++){
                if((edges[row][i] !=0) && (vertices[i].wasVisited==false)){
                    return i;
                }
            }
            return -1;
        }


        /**
         * 顶点类
         * */
        private class Vertex{
            /**
             * 顶点值
             */
            private char vertex;
            /**
             * 第index个顶点(从0开始),这么设计避免了for循环
             */
            private int index;
            /**
             * 顶点是否被访问
             */
            private boolean wasVisited;
            public Vertex(char vertex,int index){
                this.vertex = vertex;
                this.index=index;
                wasVisited = false;
            }

            @Override
            public String toString() {
                return "Vertex{" +
                        "vertex=" + vertex +
                        '}';
            }
        }
    }

    @Test
    public  void main(String[] args){
        DFSTest dfsTest = new DFSTest();
        DFSTest.Vertex[] V={
                dfsTest.new Vertex('0',0),
                dfsTest.new Vertex('1',1),
                dfsTest.new Vertex('2',2),
                dfsTest.new Vertex('3',3),
                dfsTest.new Vertex('4',4),
                dfsTest.new Vertex('5',5),
                dfsTest.new Vertex('6',6),
                dfsTest.new Vertex('7',7),
                dfsTest.new Vertex('8',8)
        };
        int[][] edges={
                {0,1,1,0,0,0,0,0,0},
                {0,0,0,1,1,0,0,0,0},
                {0,0,0,0,1,1,1,0,0},
                {0,0,0,0,1,0,0,0,0},
                {0,1,0,0,0,0,0,1,0},
                {0,0,0,0,0,0,1,0,0},
                {0,0,1,0,0,0,0,0,1},
                {0,0,0,0,0,1,0,0,0},
                {0,0,0,0,0,0,0,0,0},
        };
        DFSTest b=new DFSTest(V,edges);
        b.DFS();
    }
}


T03最小生成树

public class T03最小生成树 {

    private class MinSpanTree {
        /**
         * 邻接矩阵
         */
        int[][] matrix;
        /**
         * 表示正无穷
         */
        int MAX_WEIGHT = Integer.MAX_VALUE;
        /**
         * 顶点个数
         */
        int size;

        /**
         * 普里姆算法实现最小生成树:
         * 先初始化拿到第一个顶点相关联的权值元素放到数组中-》找到其中权值最小的顶点下标-》
         * 再根据该下标,将该下标顶点相关联的权值加入到数组中-》循环遍历处理
         */
        public void prim() {
            /**存放当前到全部顶点最小权值的数组,如果已经遍历过的顶点权值为0,无法到达的为正无穷*/
            //已连接结点中,到还未连接结点最近的距离
            int[] closeWeight = new int[size];
            /**当前到下一个最小权值顶点的最小权值*/
            int minWeight;
            /**当前到下一个最小权值的顶点*/
            int minId;
            /**权值总和*/
            int sum = 0;


            //选择第一个结点(0),然后遍历与它连接的结点的权重
            for (int i = 0; i < size; i++) {
                closeWeight[i] = matrix[0][i];
            }


            System.out.println("从顶点v0开始查找");
            //这里遍历一次,就能寻找到一个结点,还要寻找size - 1个结点
            for (int i = 0; i < size - 1; i++) {
                //把值赋值到最大
                minWeight = MAX_WEIGHT;
                minId = 0;
                //寻找离得最近的,还未连接的结点
                for (int j = 0; j < size; j++) {
                    //权值为0的顶点已经遍历过,不再计入
                    //找到离得最近的结点
                    if (closeWeight[j] > 0 && closeWeight[j] < minWeight) {
                        minWeight = closeWeight[j];
                        //保留结点位置
                        minId = j;
                    }
                }

                // 找到目标顶点minId,他的权值为minweight。
                System.out.println("找到顶点:v" + minId + " 权值为:" + minWeight);
                sum += minWeight;


                //权重标0,说明这个节点已经连接
                closeWeight[minId] = 0;
                //现在,minId结点已被连接,需要看一下它离哪些未连接结点较近,
                // 是已连接中最近的,就把距离加入tempWeight
                for (int j = 0; j < size; j++) {
                    if (closeWeight[j] != 0 && matrix[minId][j] < closeWeight[j]) {
                        closeWeight[j] = matrix[minId][j];
                    }
                }
            }

            System.out.println("最小权值总和为:" + sum);
        }

        private void createGraph(int index) {
            size = index;
            matrix = new int[index][index];
            int[] v0 = {0, 10, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 11, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT};
            int[] v1 = {10, 0, 18, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 16, MAX_WEIGHT, 12};
            int[] v2 = {MAX_WEIGHT, 18, 0, 22, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 8};
            int[] v3 = {MAX_WEIGHT, MAX_WEIGHT, 22, 0, 20, MAX_WEIGHT, MAX_WEIGHT, 16, 21};
            int[] v4 = {MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 20, 0, 26, MAX_WEIGHT, 7, MAX_WEIGHT};
            int[] v5 = {11, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 26, 0, 17, MAX_WEIGHT, MAX_WEIGHT};
            int[] v6 = {MAX_WEIGHT, 16, MAX_WEIGHT, 24, MAX_WEIGHT, 17, 0, 19, MAX_WEIGHT};
            int[] v7 = {MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 16, 7, MAX_WEIGHT, 19, 0, MAX_WEIGHT};
            int[] v8 = {MAX_WEIGHT, 12, 8, 21, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 0};
            matrix[0] = v0;
            matrix[1] = v1;
            matrix[2] = v2;
            matrix[3] = v3;
            matrix[4] = v4;
            matrix[5] = v5;
            matrix[6] = v6;
            matrix[7] = v7;
            matrix[8] = v8;
        }


    }

    @Test
    public void test01() {
        MinSpanTree graph = new MinSpanTree();
        graph.createGraph(9);
        graph.prim();
    }

    final int INF = Integer.MAX_VALUE;//使用 INF 表示两个顶点不能连通

    private class KruskalAlgorithm {

        int edgeNum; //边的个数
        char[] vertexs;//顶点数组
        int[][] matrix; //邻接矩阵


        //构造器
        public KruskalAlgorithm(char[] vertexs, int[][] matrix) {

            //初始化顶点, 复制拷贝的方式
            this.vertexs = new char[vertexs.length];
            for (int i = 0; i < vertexs.length; i++) {
                this.vertexs[i] = vertexs[i];
            }

            //初始化边, 使用的是复制拷贝的方式
            this.matrix = new int[vertexs.length][vertexs.length];
            for (int i = 0; i < vertexs.length; i++) {
                for (int j = 0; j < vertexs.length; j++) {
                    this.matrix[i][j] = matrix[i][j];
                }
            }

            //统计边的条数
            for (int i = 0; i < vertexs.length; i++) {
                for (int j = i + 1; j < vertexs.length; j++) {
                    if (this.matrix[i][j] != INF) {//可以连通,边的个数+1
                        edgeNum++;
                    }
                }
            }
        }

        /**
         * @Description: 打印邻接矩阵
         */
        public void print() {
            for (int i = 0; i < vertexs.length; i++) {
                for (int j = 0; j < vertexs.length; j++) {
                    System.out.printf("%12d", matrix[i][j]);
                }
                System.out.println();//换行
            }
        }

        /**
         * @Description: 对边进行排序(冒泡排序)
         * @Param: edges 边的集合
         */
        public void sortEdges(KData[] edges) {
            for (int i = 0; i < edges.length - 1; i++) {
                for (int j = 0; j < edges.length - 1 - i; j++) {
                    if (edges[j].weight > edges[j + 1].weight) {
                        KData temp = edges[j];
                        edges[j] = edges[j + 1];
                        edges[j + 1] = temp;
                    }
                }
            }
        }

        /**
         * @Description:
         * @Param: c 表示顶点的值,比如‘A’,‘B’...
         * @Author: xz
         * @return: 返回c 顶点的下标,如果找不到返回-1
         */
        public int getPosition(char c) {
            for (int i = 0; i < vertexs.length; i++) {
                if (vertexs[i] == c) {
                    return i;
                }
            }
            //找不到返回-1
            return -1;
        }

        /**
         * @Description: 获取图中的边放到KData[] 数组中,通过 matrix 邻接矩阵获取
         * KData[] 的形式如: [[<A, B>= 12], [<A, F>= 16],...]
         */
        public KData[] getEdges() {
            int index = 0;
            KData[] edges = new KData[edgeNum];
            for (int i = 0; i < vertexs.length; i++) {
                for (int j = i + 1; j < vertexs.length; j++) {
                    if (matrix[i][j] != INF) {
                        edges[index++] = new KData(vertexs[i], vertexs[j], matrix[i][j]);
                    }
                }
            }
            return edges;
        }

        /**
         * 功能: 获取下标为i的顶点的终点(), 用于后面判断两个顶点的终点是否相同
         * @param parent : 数组就是记录了各个顶点对应的终点是哪个,parent 数组是在遍历过程中,逐步形成
         * @param i    : 表示传入的顶点对应的下标
         * @return 返回的就是 下标为i的这个顶点对应的终点的下标
         */
        private int getEnd(int[] parent, int i) {
            while (parent[i] != 0) {
                i = parent[i];
            }
            return i;
        }

        /**
         * @Description: 克鲁斯卡尔方法
         */
        public void kruskal() {
            int index = 0; //表示最后结果数组的索引
            //这里存放着的是每个结点的父结点,
            // 刚开始默认是自己,同属于一父个结点,就属于一个帮派
            int[] parent = new int[edgeNum];
            //创建结果数组, 保存最后的最小生成树
            KData[] rets = new KData[edgeNum];

            //获取图中 所有的边的集合 , 一共有12边
            KData[] edges = getEdges();
            System.out.println("图的边的集合=" + Arrays.toString(edges) + " 共" + edges.length); //12

            //按照边的权值大小进行排序(从小到大)
            sortEdges(edges);

            //遍历edges 数组,将边添加到最小生成树中时,判断准备加入的边否形成了回路,
            // 如果没有,就加入 rets, 否则不能加入
            for (int i = 0; i < edgeNum; i++) {
                //获取到第i条边的第一个顶点(起点)
                int p1 = getPosition(edges[i].start); //p1=4
                //获取到第i条边的第2个顶点
                int p2 = getPosition(edges[i].end); //p2 = 5

                //获取p1这个顶点的父结点是谁
                int m = getEnd(parent, p1); //m = 4
                //获取p1这个顶点的父结点是谁
                int n = getEnd(parent, p2); // n = 5

                //如果m,n不是同一个,则就是不同帮派,可以添加,否则就形成了回路
                if (m != n) { //没有构成回路
                    parent[m] = n; //  parent[n] = m 这两个的意义是一样的,就是指定一个结点为另一个结点的父结点
                    rets[index++] = edges[i]; //有一条边加入到rets数组
                }
                //找到 vertexs.length - 1个边,就可以结束掉
                if (index == vertexs.length - 1) break;
            }
            //<E,F> <C,D> <D,E> <B,F> <E,G> <A,B>。
            //统计并打印 "最小生成树", 输出  rets
            System.out.println("最小生成树为=================");
            for (int i = 0; i < index; i++) {
                System.out.println(rets[i]);
            }
        }


    }


    /**
     * @Description: 创建一个类KData,它的对象实例就表示一条边

     */
    class KData {
        char start; //边的一个点
        char end; //边的另外一个点
        int weight; //边的权值

        //构造器
        public KData(char start, char end, int weight) {
            this.start = start;
            this.end = end;
            this.weight = weight;
        }

        //重写toString, 便于输出边信息
        @Override
        public String toString() {
            return "KData [<" + start + ", " + end + ">= " + weight + "]";
        }
    }

    @Test
    public void test02() {
        //定义7个顶点
        char[] vertexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        //定义克鲁斯卡尔算法的邻接矩阵  INF:表示两个顶点不能连通,0:表示顶点自己和顶点自己相连
        int matrix[][] = {
                /*A*//*B*//*C*//*D*//*E*//*F*//*G*/
                /*A*/ {0, 12, INF, INF, INF, 16, 14},
                /*B*/ {12, 0, 10, INF, INF, 7, INF},
                /*C*/ {INF, 10, 0, 3, 5, 6, INF},
                /*D*/ {INF, INF, 3, 0, 4, INF, INF},
                /*E*/ {INF, INF, 5, 4, 0, 2, 8},
                /*F*/ {16, 7, 6, INF, 2, 0, 9},
                /*G*/ {14, INF, INF, INF, 8, 9, 0}
        };

        //创建KruskalAlgorithm 对象实例
        KruskalAlgorithm kruskalAlgorithm = new KruskalAlgorithm(vertexs, matrix);

        //输出构建的邻接矩阵
        System.out.println("邻接矩阵============== \n");
        kruskalAlgorithm.print();
        System.out.println();

        System.out.println("图中的边及权值-------------------------");
        KData[] edges = kruskalAlgorithm.getEdges();
        System.out.println("排序前=" + Arrays.toString(edges));

        kruskalAlgorithm.sortEdges(edges);
        System.out.println("排序后=" + Arrays.toString(edges));

        System.out.println();
        kruskalAlgorithm.kruskal();
    }
}


T04最短路径

/**
 * 功能描述
 *
 * @author: xl
 * @date: 2022年08月05日 11:23
 */
public class T04最短路径 {
    private static final int INF = Integer.MAX_VALUE;   // 最大值

    private class MatrixUDG {

        private int mEdgNum;        // 边的数量
        private char[] mVexs;       // 顶点集合
        private int[][] mMatrix;    // 邻接矩阵


        /*
         * 创建图(自己输入数据)
         */
        public MatrixUDG() {

            // 输入"顶点数"和"边数"
            System.out.printf("input vertex number: ");
            int vlen = readInt();
            System.out.printf("input edge number: ");
            int elen = readInt();
            if (vlen < 1 || elen < 1 || (elen > (vlen * (vlen - 1)))) {
                System.out.printf("input error: invalid parameters!\n");
                return;
            }

            // 初始化"顶点"
            mVexs = new char[vlen];
            for (int i = 0; i < mVexs.length; i++) {
                System.out.printf("vertex(%d): ", i);
                mVexs[i] = readChar();
            }

            // 1. 初始化"边"的权值
            mEdgNum = elen;
            mMatrix = new int[vlen][vlen];
            for (int i = 0; i < vlen; i++) {
                for (int j = 0; j < vlen; j++) {
                    if (i == j)
                        mMatrix[i][j] = 0;
                    else
                        mMatrix[i][j] = INF;
                }
            }
            // 2. 初始化"边"的权值: 根据用户的输入进行初始化
            for (int i = 0; i < elen; i++) {
                // 读取边的起始顶点,结束顶点,权值
                System.out.printf("edge(%d):", i);
                char c1 = readChar();       // 读取"起始顶点"
                char c2 = readChar();       // 读取"结束顶点"
                int weight = readInt();     // 读取"权值"

                int p1 = getPosition(c1);
                int p2 = getPosition(c2);
                if (p1 == -1 || p2 == -1) {
                    System.out.printf("input error: invalid edge!\n");
                    return;
                }

                mMatrix[p1][p2] = weight;
                mMatrix[p2][p1] = weight;
            }
        }

        /*
         * 创建图(用已提供的矩阵)
         *
         * 参数说明:
         *     vexs  -- 顶点数组
         *     matrix-- 矩阵(数据)
         */
        public MatrixUDG(char[] vexs, int[][] matrix) {

            // 初始化"顶点数"和"边数"
            int vlen = vexs.length;

            // 初始化"顶点"
            mVexs = new char[vlen];
            for (int i = 0; i < mVexs.length; i++)
                mVexs[i] = vexs[i];

            // 初始化"边"
            mMatrix = new int[vlen][vlen];
            for (int i = 0; i < vlen; i++)
                for (int j = 0; j < vlen; j++)
                    mMatrix[i][j] = matrix[i][j];

            // 统计"边"
            mEdgNum = 0;
            for (int i = 0; i < vlen; i++)
                for (int j = i + 1; j < vlen; j++)
                    if (mMatrix[i][j] != INF)
                        mEdgNum++;
        }

        /*
         * 返回ch位置
         */
        private int getPosition(char ch) {
            for (int i = 0; i < mVexs.length; i++)
                if (mVexs[i] == ch)
                    return i;
            return -1;
        }

        /*
         * 读取一个输入字符
         */
        private char readChar() {
            char ch = '0';

            do {
                try {
                    ch = (char) System.in.read();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } while (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')));

            return ch;
        }

        /*
         * 读取一个输入字符
         */
        private int readInt() {
            Scanner scanner = new Scanner(System.in);
            return scanner.nextInt();
        }


        
        /*
         * 打印矩阵队列图
         */
        public void print() {
            System.out.printf("Martix Graph:\n");
            for (int i = 0; i < mVexs.length; i++) {
                for (int j = 0; j < mVexs.length; j++)
                    System.out.printf("%10d ", mMatrix[i][j]);
                System.out.printf("\n");
            }
        }

 

        /*
         * 获取图中的边
         */
        private EData[] getEdges() {
            int index = 0;
            EData[] edges;

            edges = new EData[mEdgNum];
            for (int i = 0; i < mVexs.length; i++) {
                for (int j = i + 1; j < mVexs.length; j++) {
                    if (mMatrix[i][j] != INF) {
                        edges[index++] = new EData(mVexs[i], mVexs[j], mMatrix[i][j]);
                    }
                }
            }

            return edges;
        }

        /*
         * 对边按照权值大小进行排序(由小到大)
         */
        private void sortEdges(EData[] edges, int elen) {

            for (int i = 0; i < elen; i++) {
                for (int j = i + 1; j < elen; j++) {

                    if (edges[i].weight > edges[j].weight) {
                        // 交换"边i"和"边j"
                        EData tmp = edges[i];
                        edges[i] = edges[j];
                        edges[j] = tmp;
                    }
                }
            }
        }

        /*
         * 获取i的终点
         */
        private int getEnd(int[] vends, int i) {
            while (vends[i] != 0)
                i = vends[i];
            return i;
        }

        /*
         * Dijkstra最短路径。
         * 即,统计图中"顶点vs"到其它各个顶点的最短路径。
         *
         * 参数说明:
         *       vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。
         *     prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,
         * 位于"顶点i"之前的那个顶点。
         *     dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。
         */
        public void dijkstra(int vs, int[] prev, int[] dist) {
            // flag[i]=true表示"顶点vs"到"顶点i"的最短路径已成功获取
            boolean[] flag = new boolean[mVexs.length];

            // 初始化
            for (int i = 0; i < mVexs.length; i++) {
                flag[i] = false;          // 顶点i的最短路径还没获取到。
                prev[i] = 0;              // 顶点i的前驱顶点为0。
                dist[i] = mMatrix[vs][i];  // 顶点i的最短路径为"顶点vs"到"顶点i"的权。
            }

            // 对"顶点vs"自身进行初始化
            flag[vs] = true;
            dist[vs] = 0;

            // 遍历mVexs.length-1次;每次找出一个顶点的最短路径。
            int k = 0;
            for (int i = 1; i < mVexs.length; i++) {
                // 寻找当前最小的路径;
                // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
                int min = INF;
                for (int j = 0; j < mVexs.length; j++) {
                    if (flag[j] == false && dist[j] < min) {
                        min = dist[j];
                        k = j;
                    }
                }
                // 标记"顶点k"为已经获取到最短路径
                flag[k] = true;

                // 修正当前最短路径和前驱顶点
                // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
                for (int j = 0; j < mVexs.length; j++) {
                    int tmp = (mMatrix[k][j] == INF ? INF : (min + mMatrix[k][j]));
                    if (flag[j] == false && (tmp < dist[j])) {
                        dist[j] = tmp;
                        prev[j] = k;
                    }
                }
            }

            // 打印dijkstra最短路径的结果
            System.out.printf("dijkstra(%c): \n", mVexs[vs]);
            for (int i = 0; i < mVexs.length; i++)
                System.out.printf("  shortest(%c, %c)=%d\n", mVexs[vs], mVexs[i], dist[i]);
        }

        /*
         * floyd最短路径。
         * 即,统计图中各个顶点间的最短路径。
         *
         * 参数说明:
         *     path -- 路径。path[i][j]=k表示,"顶点i"到"顶点j"的最短路径会经过顶点k。
         *     dist -- 长度数组。即,dist[i][j]=sum表示,"顶点i"到"顶点j"的最短路径的长度是sum。
         */
        public void floyd(int[][] path, int[][] dist) {

            // 初始化
            for (int i = 0; i < mVexs.length; i++) {
                for (int j = 0; j < mVexs.length; j++) {
                    dist[i][j] = mMatrix[i][j];    // "顶点i"到"顶点j"的路径长度为"i到j的权值"。
                    path[i][j] = j;                // "顶点i"到"顶点j"的最短路径是经过顶点j。
                }
            }

            // 计算最短路径
            for (int k = 0; k < mVexs.length; k++) {
                for (int i = 0; i < mVexs.length; i++) {
                    for (int j = 0; j < mVexs.length; j++) {
                        //k代表中间结点
                        //从i到k的距离   从k到j的距离
                        // 如果经过下标为k顶点路径比原两点间路径更短,
                        // 则更新dist[i][j]和path[i][j]
                        int tmp = (dist[i][k]==INF || dist[k][j]==INF) ? INF : (dist[i][k] + dist[k][j]);
                        //从i到j的距离,大于通过中转结点的距离
                        if (dist[i][j] > tmp) {
                            // "i到j最短路径"对应的值设,为更小的一个(即经过k)
                            dist[i][j] = tmp;
                            // "i到j最短路径"对应的路径,经过k
                            path[i][j] = path[i][k];
                        }
                    }
                }
            }

            // 打印floyd最短路径的结果
            System.out.printf("floyd: \n");
            for (int i = 0; i < mVexs.length; i++) {
                for (int j = 0; j < mVexs.length; j++)
                    System.out.printf("%2d  ", dist[i][j]);
                System.out.printf("\n");
            }
            System.out.println("path>>>>>>>>");
            for (int i = 0; i < mVexs.length; i++) {
                for (int j = 0; j < mVexs.length; j++)
                    System.out.printf("%2d  ", path[i][j]);
                System.out.printf("\n");
            }
        }



        // 边的结构体
        private class EData {
            char start; // 边的起点
            char end;   // 边的终点
            int weight; // 边的权重

            public EData(char start, char end, int weight) {
                this.start = start;
                this.end = end;
                this.weight = weight;
            }
        }

        ;


    }

    @Test
    public void test01() {
        char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int matrix[][] = {
                /*A*//*B*//*C*//*D*//*E*//*F*//*G*/
                /*A*/ {0, 12, INF, INF, INF, 16, 14},
                /*B*/ {12, 0, 10, INF, INF, 7, INF},
                /*C*/ {INF, 10, 0, 3, 5, 6, INF},
                /*D*/ {INF, INF, 3, 0, 4, INF, INF},
                /*E*/ {INF, INF, 5, 4, 0, 2, 8},
                /*F*/ {16, 7, 6, INF, 2, 0, 9},
                /*G*/ {14, INF, INF, INF, 8, 9, 0}};
        MatrixUDG pG;

        // 自定义"图"(输入矩阵队列)
        //pG = new MatrixUDG();
        // 采用已有的"图"
        pG = new MatrixUDG(vexs, matrix);

        //pG.print();   // 打印图
        //pG.DFS();     // 深度优先遍历
        //pG.BFS();     // 广度优先遍历
        //pG.prim(0);   // prim算法生成最小生成树
        //pG.kruskal(); // Kruskal算法生成最小生成树

        int[] prev = new int[pG.mVexs.length];
        int[] dist = new int[pG.mVexs.length];
        // dijkstra算法获取"第4个顶点"到其它各个顶点的最短距离
//        pG.dijkstra(3, prev, dist);
        int[][] path = new int[pG.mVexs.length][pG.mVexs.length];
        int[][] floy = new int[pG.mVexs.length][pG.mVexs.length];
        // floyd算法获取各个顶点之间的最短距离
        pG.floyd(path, floy);
    }

}

5.查找

import org.junit.Test;

import java.util.Arrays;

/**
 * 功能描述
 *
 * @author: xl
 * @date: 2022年08月07日 18:07
 */
public class T01 {

    /**
     * 顺序查找
     */
    @Test
    public void test01() {
        int[] ints = {10, 10, 10, 10, 9, 10, 10};
        for (int i = 0; i < ints.length; i++) {
            if (ints[i] == 9) {
                System.out.println("找到了");
                return;
            }
        }
        System.out.println("没找到……");
    }

    /**
     * 折半查找
     */
    private int binary_search(int arr[], int target) {
        int low = 0;
        int high = arr.length - 1;
        int middle = 0;
        while (low < high) {
            middle = (low + high) / 2;
            if (arr[middle] == target) return middle;
            if (arr[middle] > target) high = middle - 1;
            else low = middle + 1;
        }
        return -1;
    }

    @Test
    public void test02() {
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        int res = binary_search(arr, 5);
        System.out.println(res);

    }

    /**
     * 分块查找
     */
    private class T {
        private class Index implements Comparable {
            int key;
            int start;

            @Override
            public int compareTo(Object o) {
                Index o1 = (Index) o;
                return this.key - o1.key;
            }
        }

        //索引表
        Index[] indexs;
        int arr[];//查找数组
        int space;//间距

        private void creat(int[] a, int num) {
            this.arr = a;
            this.indexs = new Index[num];
            for (int i = 0; i < indexs.length; i++) {
                indexs[i] = new Index();
            }
            this.space = a.length / indexs.length;
            int j = 0;
            //将分成三块
            for (int i = 0; i < indexs.length; i++) {
                indexs[i].start = j;//确定每个区间的起始值
                j += space;//确定区间范围
                int max = 0;
                for (int k = indexs[i].start; k < j; k++) {
                    if (a[k] > max) max = a[k];
                }
                indexs[i].key = max;//确定区间的最大值
            }
            Arrays.sort(indexs);
        }

        private void search(int target) {
            int i = 0;
            while (i < indexs.length && indexs[i].key < target) {
                i++;
            }
            if (i >= indexs.length) {
                //大于所有分块
                System.out.println("不存在");
                return;
            }
            int start = indexs[i].start;
            while (start < start + space && arr[start] != target) start++;
            if (start >= start + space) {
                System.out.println("不存在");
                return;
            } else {
                System.out.println("已找到值下标:" + start);
            }
        }

    }

    @Test
    public void test03() {
        int a[] = {33, 42, 44, 38, 24, 48,
                22, 12, 13, 8, 9, 20,
                60, 58, 74, 49, 86, 53};
        T t = new T();

        t.creat(a, 3);
        t.search(12);
    }

    /**
     * 二叉排序树
     */
    private class node {//结点
        public int value;
        public node left;
        public node right;

        public node() {
        }

        public node(int value) {
            this.value = value;
            this.left = null;
            this.right = null;
        }

        public node(int value, node l, node r) {
            this.value = value;
            this.left = l;
            this.right = r;
        }
    }

    private class BinarySortTree {
        node root;//根

        public BinarySortTree() {
            root = null;
        }

        public void makeEmpty()//变空
        {
            root = null;
        }

        public boolean isEmpty()//查看是否为空
        {
            return root == null;
        }

        //各种方法
        public node findmin(node t)//查找最小返回值是node,调用查看结果时需要.value
        {
            if (t == null) {
                return null;
            } else if (t.left == null) {
                return t;
            } else return (findmin(t.left));
        }

        public node findmax(node t)//查找最大
        {
            if (t == null) {
                return null;
            } else if (t.right == null) {
                return t;
            } else return (findmax(t.right));
        }

        public boolean isContains(int x)//是否存在
        {
            node current = root;
            if (root == null) {
                return false;
            }
            while (current.value != x && current != null) {
                if (x < current.value) {
                    current = current.left;
                }
                if (x > current.value) {
                    current = current.right;
                }
                if (current == null) {
                    return false;
                }//在里面判断如果超直接返回
            }
            //如果在这个位置判断是否为空会导致current.value不存在报错
            if (current.value == x) {
                return true;
            }
            return false;
        }

        public node insert(int x)// 插入 t是root的引用
        {
            node current = root;
            if (root == null) {
                root = new node(x);
                return root;
            }
            while (current != null) {
                if (x < current.value) {
                    if (current.left == null) {
                        return current.left = new node(x);
                    } else {
                        current = current.left;
                    }
                } else if (x > current.value) {
                    if (current.right == null) {
                        return current.right = new node(x);
                    } else {
                        current = current.right;
                    }
                }
            }
            return current;//其中用不到
        }

        public node remove(int x, node t)// 删除节点
        {
            if (t == null) {
                return null;
            }
            if (x < t.value) {
                t.left = remove(x, t.left);
            } else if (x > t.value) {
                t.right = remove(x, t.right);
            } else if (t.left != null && t.right != null)// 左右节点均不空
            {
                t.value = findmin(t.right).value;// 找到右侧最小值替代
                t.right = remove(t.value, t.right);
            } else // 左右单空或者左右都空
            {
                if (t.left == null && t.right == null) {
                    t = null;
                } else if (t.right != null) {
                    t = t.right;
                } else if (t.left != null) {
                    t = t.left;
                }
                return t;
            }
            return t;
        }
    }

}


1.二叉排序树

  /**
     * 二叉排序树
     */
    private class Node2 {
        int value;
        private Node2 left;
        private Node2 right;

        public Node2(int value) {
            this.value = value;
        }

        public Node2(int value, Node2 left, Node2 right) {
            this.value = value;
            this.left = left;
            this.right = right;
        }

        public Node2() {
        }
    }

    private class BinarySortTree {
        Node2 root;

        private void insert(int x) {
            Node2 cur = root;
            if (root == null) {
                root = new Node2(x);
                return;
            }
            while (cur != null) {
                if (cur.value > x) {
                    if (cur.left == null) {
                        cur.left = new Node2(x);
                        return;
                    } else {
                        cur = cur.left;
                    }
                } else {
                    //cur.value <=x
                    if (cur.right == null) {
                        cur.right = new Node2(x);
                        return;
                    } else {
                        cur = cur.right;
                    }
                }
            }
        }

        private void search(int tar) {
            if (root == null) {
                System.out.println("无");
                return;
            }
            Node2 cur = root;
            while (cur != null) {
                if (cur.value == tar) {
                    System.out.println("找到了");
                    return;
                }
                if (cur.value < tar) {
                    cur = cur.right;
                } else {
                    cur = cur.left;
                }
            }
            System.out.println("无");
        }

        private Node2 findMax(Node2 node) {
            if (node == null) return null;
            else if (node.right == null) {
                return node;
            } else {
                return findMax(node.right);
            }
        }

        private Node2 findMax() {
            return findMax(root);
        }

        private Node2 findMin(Node2 node) {
            if (node == null) return null;
            else if (node.left == null) {
                return node;
            } else {
                return findMin(node.left);
            }
        }

        private Node2 findMin() {
            return findMin(root);
        }

        private void remove(int tar) {
            if (root == null) {
                System.out.println("为空");
                return;
            }
            Node2 cur = root;
            while (cur != null) {
                if (cur.value == tar) {
                    System.out.println("找到了");
                    if (cur.left != null && cur.right != null) {
                        Node2 min = findMin(cur.right);
                    	cur.value  = min.value;
                    	min.value = tar;
                    	cur.right = remove2(tar,cur.right);
                    } else {
                        if (cur.left == null && cur.right == null) {
                            cur = null;
                        } else if (cur.right != null) {
                            cur = cur.right;
                        } else {
                            cur = cur.left;
                        }
                        return;
                    }
                }
                if (cur.value < tar) {
                    cur = cur.right;
                } else {
                    cur = cur.left;
                }
            }
        }

        private Node2 remove2(int tar, Node2 cur) {
            if (cur == null) {
                System.out.println("为空");
                return null;
            }
            if (cur.value < tar) {
                cur.right = remove2(tar,cur.right);
            } else if (cur.value>tar){
                cur.left = remove2(tar,cur.left);
            }else if (cur.value == tar) {
                System.out.println("找到了");
                if (cur.left != null && cur.right != null) {
                    Node2 max = findMax(cur.right);
                    cur.value = max.value;
                    cur.right = remove2(tar,cur.right);
                } else {
                    if (cur.left == null && cur.right == null) {
                        cur = null;
                    } else if (cur.right != null) {
                        cur = cur.right;
                    } else {
                        cur = cur.left;
                    }
                    return cur;
                }
            }
            this.root = cur;
            return cur;
        }

        private void remove2(int tar){
            remove2(tar,root);
        }


        //层次遍历
        private void leverPrint() {
            if (root == null) {
                System.out.println("为空");
                return;
            }
            Queue<Node2> queue = new LinkedList<>();
            queue.add(root);
            while (!queue.isEmpty()) {
                Node2 poll = queue.poll();
                if (poll.left != null) queue.add(poll.left);
                if (poll.right != null) queue.add(poll.right);
                System.out.print(poll.value + " ");
            }
        }

        private void prePrint(Node2 node) {
            if (node != null) {
                System.out.print(node.value + " ");
                prePrint(node.left);
                prePrint(node.right);
            }
        }

        private void prePrint() {
            if (root == null) {
                System.out.println("空");
                return;
            }
            prePrint(root);
        }

        private void centerPrint(Node2 node) {
            if (node != null) {
                centerPrint(node.left);
                System.out.print(node.value + " ");
                centerPrint(node.right);
            }
        }

        private void centerPrint() {
            if (root == null) {
                System.out.println("空");
                return;
            }
            centerPrint(root);
        }

        private void postPrint(Node2 node) {
            if (node != null) {
                postPrint(node.left);
                postPrint(node.right);
                System.out.print(node.value + " ");
            }
        }

        private void postPrint() {
            if (root == null) {
                System.out.println("空");
                return;
            }
            postPrint(root);
        }

        //求元素个数
        private int getSize(Node2 root){
            if (root == null){
                return 0;
            }
            return getSize(root.left)+getSize(root.right)+1;
        }

        private int getSize(){
            return getSize(root);
        }
        //求树的高度
        private int getHeight(Node2 node){
            if (node == null){
                return 0;
            }else {
                int left = getHeight(node.left);
                int right = getHeight(node.right);
                return (left>right)?(left+1):(right+1);
            }
        }

        private int getHeight(){
            return getHeight(root);
        }
    }

    @Test
    public void test04() {
        BinarySortTree binarySortTree = new BinarySortTree();
        binarySortTree.insert(1);
        binarySortTree.insert(2);
        binarySortTree.insert(3);
        binarySortTree.insert(6);
        binarySortTree.insert(5);
        binarySortTree.insert(4);
//        System.out.println(binarySortTree.getSize());
        System.out.println(binarySortTree.getHeight());

//        binarySortTree.remove(5);
//        binarySortTree.leverPrint();
//        System.out.println();
//        binarySortTree.prePrint();
//        System.out.println();
//        binarySortTree.centerPrint();
//        System.out.println();
//        binarySortTree.postPrint();
//        binarySortTree.search(9);
//        System.out.println(binarySortTree.findMax().value);
//        System.out.println(binarySortTree.findMin().value);

    }

2.平衡二叉树

 private class AvlTree2 {
        private AvlNode root;

        private AvlNode insert(AvlNode node, int data) {

            if (node == null) {
                node = new AvlNode(data);
                node.height = 1;
                return node;
            }
            if (node.data < data) {
                node.rightChild = insert(node.rightChild,data);
                node.height =  Math.max(getHeight(node.rightChild),getHeight(node.leftChild))+1;
                if (getHeight(node.rightChild) - getHeight(node.leftChild)  == 2){
                    if (node.rightChild.data<data){//右右
                        node = rotateLeft(node);
                    }else {//右左
                        node = rotateRightLeft(node);
                    }
                }
            } else {
                //node.data>=data;
                node.leftChild = insert(node.leftChild,data);
                node.height =  Math.max(getHeight(node.rightChild),getHeight(node.leftChild))+1;
                if (getHeight(node.rightChild) - getHeight(node.leftChild)  == -2){
                    if (node.leftChild.data<data){//左右
                        node = rotateLeftRight(node);
                    }else {//左左
                        node = rotateRight(node);
                    }
                }
            }
            return node;
        }
        private void insert(int data){
            root = insert(root,data);
        }
        private AvlNode rotateRight(AvlNode parent) {//左左
            AvlNode center = parent.leftChild;
            parent.leftChild = center.rightChild;
            center.rightChild = parent;
            parent.height = Math.max(getHeight(parent.leftChild),getHeight(parent.rightChild))+1;
            center.height = Math.max(getHeight(center.leftChild),getHeight(center.rightChild))+1;
            return center;

        }
        private AvlNode rotateRightLeft(AvlNode parent) {//右左
            parent.rightChild = rotateRight(parent.rightChild);
            parent = rotateLeft(parent);
            return parent;
        }
        private AvlNode rotateLeft(AvlNode parent) {//右右
            AvlNode center = parent.rightChild;
            parent.rightChild = center.leftChild;
            center.leftChild = parent;
            parent.height = Math.max(getHeight(parent.leftChild),getHeight(parent.rightChild))+1;
            center.height = Math.max(getHeight(center.leftChild),getHeight(center.rightChild))+1;
            return center;
        }
        private AvlNode rotateLeftRight(AvlNode parent) {
            parent.leftChild = rotateLeft(parent.leftChild);
            parent = rotateRight(parent);
            return parent;
        }
        private int getHeight(AvlNode node) {
            if (node == null){
                return 0;
            }else {
                return node.height;
            }
        }

        private AvlNode deleteMin(AvlNode node){
            if (node == null) return node;
            //当node.left == null时,说明node是最小的,直接舍弃掉
            if (node.leftChild == null) return node.rightChild;
            node.leftChild = deleteMin(node.leftChild);
            if (getHeight(node.rightChild) - getHeight(node.leftChild) == 2){
                node = rotateLeft(node);
            }
            return node;
        }
        public void deleteMin() {
            root = deleteMin(root);
        }

        private AvlNode deleteMax(AvlNode node){
     		 if (node == null) return node;
            //当node.left == null时,说明node是最小的,直接舍弃掉
            if (node.rightChild == null)
                return node.leftChild;
            node.rightChild = deleteMax(node.rightChild);
            if (getHeight(node.leftChild) - getHeight(node.rightChild) == 2){
                node = rotateRight(node);
            }
            return node;
        }

        public void deleteMax() {
            root = deleteMax(root);
        }
        private AvlNode delete(AvlNode node,int data){
            if (node == null) return node;
            if (node.data<data){
                node.rightChild = delete(node.rightChild,data);
                if (getHeight(node.leftChild)- getHeight(node.rightChild) ==2){
                    node = rotateLeft(node.rightChild);
                }
            }else if (node.data>data){
                node.leftChild = delete(node.leftChild,data);
                if (getHeight(node.rightChild)-getHeight(node.leftChild) ==2){
                    node = rotateRight(node.rightChild);
                }
            }else if (node.data == data){
                //找到要删除的点了
                if (node.leftChild == null) return node.rightChild;
                if (node.rightChild == null) return node.leftChild;
                //左右节点都有
                AvlNode min = getMin(node.rightChild);
                min.rightChild = deleteMin(node.rightChild);
                min.leftChild = node.leftChild;
                node = min;
                if (getHeight(node.leftChild) - getHeight(node.rightChild) == 2){
                    node = rotateRight(node);
                }

            }

            return node;
        }

        private void delete(int data){
            root = delete(root,data);
        }

        private AvlNode getMin(AvlNode node) {
            if (node == null)return node;
            while (node.leftChild!=null)node = node.leftChild;
            return node;
        }

        private void leverPrint(AvlNode node){
            if (node == null){
                System.out.println("无");
                return;
            }
            Queue<AvlNode> queue = new LinkedList<>();
            queue.add(node);
            while (!queue.isEmpty()){
                AvlNode poll = queue.poll();
                System.out.print(poll.data+" ");
                if (poll.leftChild!=null) queue.add(poll.leftChild);
                if (poll.rightChild!=null)queue.add(poll.rightChild);
            }
            System.out.println("高度:"+getHeight(node));
        }
        private void leverPrint(){
            leverPrint(root);

        }
    }

    @Test
    public void test05() {
        AvlTree2 avlTree = new AvlTree2();
        Scanner scanner = new Scanner(System.in);
        int i1 = scanner.nextInt();

        for (int i = 0; i < i1; i++) {
            avlTree.insert(scanner.nextInt());
        }
        //1 2 3 4 5
        avlTree.leverPrint();
        avlTree.delete(5);
        avlTree.leverPrint();
    }

6. 排序

import org.junit.Test;

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

/**
 * 功能描述
 *
 * @author: xl
 * @date: 2022年08月08日 14:12
 */
public class T01 {
    /**
     * 冒泡排序
     */
    @Test
    public void test01() {
        int[] arr = {1, 2, 3, 6, 5, 4};
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
//                if (arr[j]>arr[j+1]){
//                    int temp  = arr[j+1];
//                    arr[j+1] =arr[j];
//                    arr[j]  = temp;
//                }
                if (arr[j] < arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 冒泡排序的优化
     */
    @Test
    public void test02() {
        int[] arr = {1, 2, 3, 6, 5, 4};
        for (int i = 0; i < arr.length - 1; i++) {
            boolean flag = true;
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j + 1];
                    arr[j + 1] = arr[j];
                    arr[j] = temp;
                    flag = false;
                }
            }
            if (flag) {
                //说明排序已经有序,没不要在进行排序了
                break;
            }
        }
        System.out.println(Arrays.toString(arr));
    }

    int[] arr = {1, 2, 3, 6, 5, 4};

    /**
     * 交换函数,后者覆盖前者
     *
     * @param pre
     * @param next
     * @return
     */
    private int[] swap(int pre, int next) {
        int swap = arr[pre];
        arr[pre] = arr[next];
        arr[next] = swap;
        return arr;
    }

    /**
     * 前者覆盖后者
     *
     * @param pre
     * @param next
     * @return
     */
    private int[] swap2(int pre, int next) {
        int swap = arr[next];
        arr[next] = arr[pre];
        arr[pre] = swap;
        return arr;
    }


    /**
     * 简单选择排序
     */
    @Test
    public void test03() {
        for (int i = 0; i < arr.length - 1; i++) {
            int temp = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[temp] > arr[j]) {
                    //保留最小值
                    temp = j;
                }
            }

            //交换,后者覆盖前者
            arr = swap(i, temp);
        }
        System.out.println(Arrays.toString(arr));
    }


    /**
     * 直接插入排序
     */
    @Test
    public void test04() {
        int j = 0;
        for (int i = 1; i < arr.length; i++) { //循环从第2个元素开始
            //和i之前的元素进行比较,如果后者小于前者
            if (arr[i] < arr[i - 1]) {
                //保留现在位置的元素
                int temp = arr[i];
                //如果前面的元素大于后面的元素
                for (j = i - 1; j >= 0 && arr[j] > temp; j--) {
                    //前面的值后移,j的值就为空
                    arr[j + 1] = arr[j];
                }
                //说明当前的值比较小,到了这,找到了合适的位置
                arr[j + 1] = temp;//此处就是a[j+1]=temp;
            }
        }
        System.out.println(Arrays.toString(arr));
    }

    public static void shellSortSmallToBig(int[] data) {
        int j = 0;
        int temp = 0;

        //这个循环算出增量
        for (int increment = data.length / 2; increment > 0; increment /= 2) {
            //increment每次都要/2       5,2,1
            System.out.println("increment:" + increment);
            //length:10,
            /**
             * 5,6,7,8,9,10
             * 2,3,4,5,6,7,8,9,10
             * 1,2,3,4,5,6,7,8,9,10
             */

            /**
             * 插入排序,从increment开始,
             */
            for (int i = increment; i < data.length; i++) {
                // System.out.println("i:" + i);
                //保留i这个位置,和前面的位置进行比较
                temp = data[i];
                for (j = i - increment; j >= 0; j -= increment) {
                    // System.out.println("j:" + j);
                    // System.out.println("temp:" + temp);
                    // System.out.println("data[" + j + "]:" + data[j]);
                    if (temp < data[j]) {
                        data[j + increment] = data[j];
                    } else {
                        break;
                    }
                }
                data[j + increment] = temp;
            }

            for (int i = 0; i < data.length; i++)
                System.out.print(data[i] + " ");
            System.out.println();
        }
    }

    @Test
    public void test05() {
        int[] data = new int[]{26, 53, 67, 48, 57, 13, 48, 32, 60, 50};
        shellSortSmallToBig(data);
        System.out.println(Arrays.toString(data));
    }


    /**
     * 创建堆,
     *
     * @param arr 待排序列
     */
    private void heapSort(int[] arr) {
        //创建堆,从最后一个节点往上构建堆,parent = (i-1)/2
        for (int i = (arr.length - 1) / 2; i >= 0; i--) {
            //从第一个非叶子结点从下至上,从右至左调整结构
            adjustHeap(arr, i, arr.length);
        }

        //调整堆结构+交换堆顶元素与末尾元素
        for (int i = arr.length - 1; i > 0; i--) {
            //将堆顶元素与末尾元素进行交换
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;

            //重新对堆进行调整,只需要调整最顶上的三个值,从上往下
            adjustHeap(arr, 0, i);
        }
    }

    /**
     * 调整堆
     *
     * @param arr    待排序列
     * @param parent 父节点
     * @param length 待排序列尾元素索引
     */
    private void adjustHeap(int[] arr, int parent, int length) {
        //将temp作为父节点,从父节点开始,保证下面的子节点都是堆
        int temp = arr[parent];
        //左孩子
        int lChild = 2 * parent + 1;
        //只要子节点不越界循环,也就是递归,因为如果父节点交换,必然也要继续往下交换
        while (lChild < length) {
            //右孩子
            int rChild = lChild + 1;
            // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
            if (rChild < length && arr[lChild] < arr[rChild]) {
                lChild++;
            }

            // 如果父结点的值已经大于孩子结点的值,则直接结束
            if (temp >= arr[lChild]) {
                break;
            }

            // 把孩子结点的值赋给父结点
            arr[parent] = arr[lChild];

            //选取孩子结点的左孩子结点,继续向下筛选,也只有这样,才能改变循环
            parent = lChild;
            lChild = 2 * lChild + 1;
        }
        //父节点的值已经被调换,然后就交换过来
        arr[parent] = temp;
    }

    /**
     * 堆排序演示
     *
     * @author Lvan
     */

    @Test
    public void test06() {
//        int[] arr = {5, 1, 7, 3, 1, 6, 9, 4};
        int[] arr = {16, 7, 3, 20, 17, 8};

        heapSort(arr);

        for (int i : arr) {
            System.out.print(i + " ");
        }
    }


    /**
     * 并归
     * @param a
     * @param low
     * @param mid
     * @param high
     */
    public void merge(int[] a, int low, int mid, int high) {
        //开辟一个临时数组
        int[] temp = new int[high - low + 1];
        int i = low;// 左指针
        int j = mid + 1;// 右指针
        int k = 0;//临时数组的下标
        // 把较小的数先移到新数组中
        //只要两个小的数组,只要有一个还有值,就继续比较
        while (i <= mid && j <= high) {
            //如果左数组小于右数组
            if (a[i] < a[j]) {
                //临时数组下标+1,左指针+1
                temp[k++] = a[i++];
            } else {
                //如果左数组大于右数组
                //临时数组下标+!,右指针+1
                temp[k++] = a[j++];
            }
        }
        //到了这里,要么两个数组都没了,要么还剩一方
        // 把左边剩余的数移入数组
        while (i <= mid) {
            temp[k++] = a[i++];
        }
        // 把右边边剩余的数移入数组
        while (j <= high) {
            temp[k++] = a[j++];
        }
        // 把新数组中的数覆盖nums数组
        //这里会从覆盖掉low到high区间的数组
        for (int k2 = 0; k2 < temp.length; k2++) {
            a[k2 + low] = temp[k2];
        }
    }

    public void mergeSort(int[] a, int low, int high) {
        //找到中间
        int mid = (low + high) / 2;
        //只要low<high,就会继续执行,直到只剩下一个,这样就已经有序了
        if (low < high) {
            // 左边,从最小点到中点
            mergeSort(a, low, mid);
            // 右边,从中点+1,到最大点
            mergeSort(a, mid + 1, high);
            // 分完成后,左右归并,怎么分的,就怎样归并

            merge(a, low, mid, high);
            System.out.println(Arrays.toString(a));
        }

    }

    /**
     * 归并排序
     */
    @Test
    public void test07() {
        int a[] = {51, 46, 20, 18, 65, 97, 82, 30, 77, 50};
        mergeSort(a, 0, a.length - 1);
        System.out.println("排序结果:" + Arrays.toString(a));
    }



    /*
     * 快速排序
     *
     * 参数说明:
     *     a -- 待排序的数组
     *     l -- 数组的左边界(例如,从起始位置开始排序,则l=0)
     *     r -- 数组的右边界(例如,排序截至到数组末尾,则r=a.length-1)
     */
    public  void quickSort(int[] a, int l, int r) {

        //只要元素大于一个,就要开始排序
        if (l < r) {
            int i,j,x;

            i = l;
            j = r;
            //取最左面的值作为基准值
            x = a[i];
            //当i和j重叠时,这一次排序就结束了,标注位置flag
            while (i < j) {

                while(i < j && a[j] > x)
                    j--; // 从右向左找第一个小于x的数min
                if(i < j)
                    a[i++] = a[j];//把min放到左边,然后转向
                while(i < j && a[i] < x)
                    i++; // 从左向右找第一个大于x的数,max
                if(i < j)
                    a[j--] = a[i];//把max放到右边,然后转向
            }
            //结束一轮交换,然后把基准值填充上去
            a[i] = x;//或者 a[j] = x
            //从1到flag-1的值在进行排序
            quickSort(a, l, i-1); /* 递归调用 */
            //从flag+1到r的值在进行排序
            quickSort(a, i+1, r); /* 递归调用 */
        }
    }

    @Test
    public  void test08() {
        int i;
        int a[] = {30,40,60,10,20,50};

        System.out.printf("before sort:");
        for (i=0; i<a.length; i++)
            System.out.printf("%d ", a[i]);
        System.out.printf("\n");


        quickSort(a, 0, a.length-1);

        System.out.printf("after  sort:");
        for (i=0; i<a.length; i++)
            System.out.printf("%d ", a[i]);
        System.out.printf("\n");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值