数据结构与算法笔记

目录

扩展欧几里得算法(ax+by=gcd(a,b))

稀疏数组

环形队列

链表

单链表结点的添加与删除

单链表反转

逆序打印单链表

双向链表的遍历添加与删除

环形链表

逆波兰表达式算法

八皇后问题

八大排序算法

冒泡排序

选择排序

插入排序

希尔排序

归并排序

快速排序

基数排序

堆排序

查找算法

二分查找

差值查找

哈希表

二叉树

顺序存储二叉树

线索化二叉树​编辑

赫夫曼树

二叉排序树

AVL树(平衡二叉树)

深度优先(dfs)

广度优先(bfs)

分治算法

动态规划

KMP算法(字符串匹配问题)

贪心算法

普里姆算法(最小生成树)

克鲁斯卡尔算法(最小生成树)

Dijkstra算法(一点的最短路径)

弗洛伊德算法(任意点的最短路径)

 马踏棋盘算法(dfs)


扩展欧几里得算法(ax+by=gcd(a,b))

x,y是整数,通过如下算法求出(x,y)

返回的是最大公约数,x,y的值通过引用(数组也行)传回

稀疏数组

public class SparseArray {

	public static void main(String[] args) {
		// 创建一个原始的二维数组 11 * 11
		// 0: 表示没有棋子, 1 表示 黑子 2 表蓝子
		int chessArr1[][] = new int[11][11];
		chessArr1[1][2] = 1;
		chessArr1[2][3] = 2;
		chessArr1[4][5] = 2;
		// 输出原始的二维数组
		System.out.println("原始的二维数组~~");
		for (int[] row : chessArr1) {
			for (int data : row) {
				System.out.printf("%d\t", data);
			}
			System.out.println();
		}

		// 将二维数组 转 稀疏数组的思
		// 1. 先遍历二维数组 得到非0数据的个数
		int sum = 0;
		for (int i = 0; i < 11; i++) {
			for (int j = 0; j < 11; j++) {
				if (chessArr1[i][j] != 0) {
					sum++;
				}
			}
		}

		// 2. 创建对应的稀疏数组
		int sparseArr[][] = new int[sum + 1][3];
		// 给稀疏数组赋值
		sparseArr[0][0] = 11;
		sparseArr[0][1] = 11;
		sparseArr[0][2] = sum;
		
		// 遍历二维数组,将非0的值存放到 sparseArr中
		int count = 0; //count 用于记录是第几个非0数据
		for (int i = 0; i < 11; i++) {
			for (int j = 0; j < 11; j++) {
				if (chessArr1[i][j] != 0) {
					count++;
					sparseArr[count][0] = i;
					sparseArr[count][1] = j;
					sparseArr[count][2] = chessArr1[i][j];
				}
			}
		}
		
		// 输出稀疏数组的形式
		System.out.println();
		System.out.println("得到稀疏数组为~~~~");
		for (int i = 0; i < sparseArr.length; i++) {
			System.out.printf("%d\t%d\t%d\t\n", sparseArr[i][0], sparseArr[i][1], sparseArr[i][2]);
		}
		System.out.println();
		
		//将稀疏数组 --》 恢复成 原始的二维数组
		/*
		 *  1. 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组,比如上面的  chessArr2 = int [11][11]
			2. 在读取稀疏数组后几行的数据,并赋给 原始的二维数组 即可.
		 */
		
		//1. 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组
		
		int chessArr2[][] = new int[sparseArr[0][0]][sparseArr[0][1]];
		
		//2. 在读取稀疏数组后几行的数据(从第二行开始),并赋给 原始的二维数组 即可
		
		for(int i = 1; i < sparseArr.length; i++) {
			chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
		}
		
		// 输出恢复后的二维数组
		System.out.println();
		System.out.println("恢复后的二维数组");
		
		for (int[] row : chessArr2) {
			for (int data : row) {
				System.out.printf("%d\t", data);
			}
			System.out.println();
		}
	}

}

环形队列

class CircleArray {
	private int maxSize; // 表示数组的最大容量
	//front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素 
	//front 的初始值 = 0
	private int front; 
	//rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.
	//rear 的初始值 = 0
	private int rear; // 队列尾
	private int[] arr; // 该数据用于存放数据, 模拟队列
	
	public CircleArray(int arrMaxSize) {
		maxSize = arrMaxSize;
		arr = new int[maxSize];
	}
	
	// 判断队列是否满
	public boolean isFull() {
		return (rear  + 1) % maxSize == front;
	}
	
	// 判断队列是否为空
	public boolean isEmpty() {
		return rear == front;
	}
	
	// 添加数据到队列
	public void addQueue(int n) {
		// 判断队列是否满
		if (isFull()) {
			System.out.println("队列满,不能加入数据~");
			return;
		}
		//直接将数据加入
		arr[rear] = n;
		//将 rear 后移, 这里必须考虑取模
		rear = (rear + 1) % maxSize;
	}
	
	// 获取队列的数据, 出队列
	public int getQueue() {
		// 判断队列是否空
		if (isEmpty()) {
			// 通过抛出异常
			throw new RuntimeException("队列空,不能取数据");
		}
		// 这里需要分析出 front是指向队列的第一个元素
		// 1. 先把 front 对应的值保留到一个临时变量
		// 2. 将 front 后移, 考虑取模
		// 3. 将临时保存的变量返回
		int value = arr[front];
		front = (front + 1) % maxSize;
		return value;

	}
	
	// 显示队列的所有数据
	public void showQueue() {
		// 遍历
		if (isEmpty()) {
			System.out.println("队列空的,没有数据~~");
			return;
		}
		// 思路:从front开始遍历,遍历多少个元素
		// 动脑筋
		for (int i = front; i < front + size() ; i++) {
			System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
		}
	}
	
	// 求出当前队列有效数据的个数
	public int size() {
		// rear = 2
		// front = 1
		// maxSize = 3 
		return (rear + maxSize - front) % maxSize;   
	}
	
	// 显示队列的头数据, 注意不是取出数据
	public int headQueue() {
		// 判断
		if (isEmpty()) {
			throw new RuntimeException("队列空的,没有数据~~");
		}
		return arr[front];
	}
}

链表

单链表结点的添加与删除

public void add(HereNode o) {
        HereNode temp = head;
        while (true) {
            if (temp.next == null)
                break;
            else
                temp = temp.next;
        }
        temp.next = o;
    }

    public void addbyorder(HereNode o) {
        HereNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null)
                break;
            if (temp.next.no > o.no)
                break;
            else if (temp.next.no == o.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            System.out.printf("编号%d已存在,不能添加\n", temp.no);
        } else {
            o.next = temp.next;
            temp.next = o;
        }
    }

    public void del(int no) {
        HereNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null)
                break;
            if (temp.next.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.next = temp.next.next;
        } else
            System.out.printf("编号为%d的结点不存在,删除失败", no);
    }

单链表反转

public static void reverseList(HereNode head) {
        if (head.next == null || head.next.next == null)
            return;
        HereNode cur = head.next;
        HereNode next = null;
        HereNode reversehead = new HereNode(0, "");
        while (cur != null) {
            next = cur.next;
            cur.next = reversehead.next;
            reversehead.next = cur;
            cur = next;
        }
        head.next = reversehead.next;
    }

逆序打印单链表

 public static void reversePrint(HereNode head) {
        if (head.next == null)
            return;
        HereNode cur = head.next;
        Stack<HereNode> stack = new Stack<>();
        while (cur != null) {
            stack.push(cur);
            cur = cur.next;
        }
        while (stack.size() > 0) {
            System.out.println(stack.pop());
        }
    }

双向链表的遍历添加与删除

环形链表

class Circlesinglelinkedlist {
    private Boy first = null;

    public void addBoy(int nums) {
        Boy curboy = null;
        for (int i = 1; i <= nums; i++) {
            Boy boy = new Boy(i);
            if (i == 1) {
                curboy = boy;
                first = boy;
                boy.setNext(boy);
            } else {
                curboy.setNext(boy);
                boy.setNext(first);
                curboy = boy;
            }
        }
    }

    public void showBoy() {
        if (first == null) {
            System.out.println("没有任何小孩!");
            return;
        }
        Boy curboy = first;
        while (true) {
            System.out.printf("当前小孩编号为:%d\n", curboy.getId());
            if (curboy.getNext() == first) {
                break;
            }
            curboy = curboy.getNext();
        }
    }

    public void countBoy(int startnum, int countnum, int nums) {
        Boy helper = first;
        while (true) {
            if (helper.getNext() == first)
                break;
            helper = helper.getNext();
        }
        for (int i = 0; i < startnum - 1; i++) {
            first = first.getNext();
            helper = helper.getNext();
        }
        while (true) {
            if (first == helper)
                break;
            for (int i = 0; i < countnum - 1; i++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            System.out.printf("出圈的男孩编号为:%d\n", first.getId());
            first = first.getNext();
            helper.setNext(first);
        }
        System.out.printf("最后留在圈中的小孩编号为:%d\n",first.getId()
        );
    }
}

class Arraystack_ {
    private int maxSize;
    private int stack[];
    private int top = -1;

    public Arraystack_(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    boolean isFull() {
        return top == maxSize - 1;
    }

    boolean isEmpty() {
        return top == -1;
    }

    public void push(int n) {
        if (isFull()) {
            throw new RuntimeException("栈满,无法压入");
        }
        stack[++top] = n;
    }

    public void pop() {
        if(isEmpty())
            throw new RuntimeException("栈空,无法弹出");
        int value = stack[top];
        top--;
        System.out.printf("出栈的数字为:%d\n", value);
    }

    public void showstack() {
        for (int i = top; i >= 0; i--) {
            System.out.printf("a[%d]=%d\n", i, stack[i]);
        }
    }

}

逆波兰表达式算法

public class PolandNotation {
    public static void main(String[] args) {
        String expression = "((3+14)*9-5)+91";
        List<String> strings = toInfixList(expression);
        System.out.println(strings);
        List<String> strings1 = toSuffixList(strings);
        System.out.println(strings1);
        System.out.println(cal(strings1));
    }

    public static List<String> toInfixList(String expression) {
        ArrayList<String> strings = new ArrayList<>();
        int index = 0;
        char c;
        String key;
        while (true) {
            if ((c = expression.charAt(index)) < 48 || (c = expression.charAt(index)) > 57) {
                strings.add(c + "");
                index++;
            } else {
                key = "";
                while (index < expression.length() && (c = expression.charAt(index))
                        >= 48 && (c = expression.charAt(index)) <= 57) {
                    key += c;
                    index++;
                }
                strings.add(key);
            }
            if (index == expression.length() )
                break;
        }
        return strings;
    }

    public static List<String> toSuffixList(List<String> strings) {
        Stack<String> s1 = new Stack<>();
        ArrayList<String> s2 = new ArrayList<>();
        for (String string : strings) {
            if (string.matches("\\d+"))
                s2.add(string);
            else if (string.equals("("))
                s1.push(string);
            else if (string.equals(")")) {
                while (!s1.peek().equals("(")) {
                    s2.add(s1.pop());
                }
                s1.pop();
            }
            else {
                while (s1.size()>0&&Priority.getpriority(string) <=Priority.getpriority(s1.peek()) )
                    s2.add(s1.pop());
                s1.push(string);

            }
        }
        while (s1.size()!=0)
            s2.add(s1.pop());
        return s2;
    }

    public static int cal(List<String> list) {
        int res = 0;
        Stack<String> strings = new Stack<>();
        for (String s : list) {
            if (s.matches("\\d+"))
                strings.push(s);
            else {
                int num1 = Integer.parseInt(strings.pop());
                int num2 = Integer.parseInt(strings.pop());
                if (s.equals("+"))
                    res = num1 + num2;
                else if (s.equals("-"))
                    res = num2 - num1;
                else if (s.equals("*"))
                    res = num1 * num2;
                else if (s.equals("/"))
                    res = num2 / num1;
                else
                    throw new RuntimeException("输入错误");
                strings.push(res + "");
            }
        }
        return Integer.parseInt(strings.pop());
    }
}


class Priority {
    public static int getpriority(String s) {
        if (s.equals("+") || s.equals("-"))
            return 1;
        else if(s.equals("*")||s.equals("/"))
            return 2;
        else
            return 0;
    }
}

八皇后问题

public class queen8 {

    public static void main(String[] args) {
        queen8 queen8 = new queen8();
        queen8.check(0);
        System.out.printf("总共%d种解法\n", count);
        System.out.printf("判断次数为%d", judgecount);

    }

    int[] arr = new int[8];
    static int count = 0;
    static int judgecount = 0;

    public boolean judge(int n) {
        judgecount++;
        for (int i = 0; i < n; i++) {
            if (arr[i] == arr[n] || Math.abs(n - i) == Math.abs(arr[n] - arr[i]))
                return false;
        }
        return true;
    }

    public void print() {
        count++;
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public void check(int n) {
        if (n == 8) {
            print();
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            arr[n] = i;
            if (judge(n))
                check(n + 1);
        }
    }
}

八大排序算法

冒泡排序

 public static void bubblesort(int[] arr) {
        int temp = 0;
        boolean flag = false;
        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]) {
                    flag = true;
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            if (!flag)//优化处理:若未进入内层循环,则说明已经有序,不必往下继续执行,break即可
                break;
            else
                flag = false;
        }
    }

选择排序

public static void selectsort(int a[]) {
        for (int i = 0; i < a.length - 1; i++) {
            int minindex = i;//假定当前为最小值的下标
            for (int j = i + 1; j < a.length; j++) {
                if (a[j] < a[minindex])
                    minindex = j;//确定本轮最小值下标
            }
            if (minindex != i) {//优化处理:若假定的和确定后的为同一下标则无需交换
                int temp = a[minindex];//否则交换
                a[minindex] = a[i];
                a[i] = temp;
            }
        }
    }

插入排序

public static void insertsort(int a[]) {
        for (int i = 1; i < a.length; i++) {
            int insertindex = i - 1;//插入点
            int insertvalue = a[i];//插入值
            while (insertindex >= 0 && insertvalue < a[insertindex]) {
                a[insertindex + 1] = a[insertindex];
                insertindex--;
            }
            a[insertindex + 1] = insertvalue;//插入值插入到插入点
        }
    }

希尔排序

 public static void shellsort(int arr[]){
        for (int gap =arr.length/2 ; gap>0; gap/=2) {//沟为当前长度的一半
            for(int i=gap;i<arr.length;i++){
              int j=i;//插入点的后一个
              int temp=arr[j];//插入值
              if(arr[j]<arr[j-gap]){//以下代码类似于插入排序
                  while(j-gap>=0&&temp<arr[j-gap]){
                      arr[j]=arr[j-gap];
                      j-=gap;
                  }
                  arr[j]=temp;
              }
            }
        }
    }

归并排序

  public static void merge(int a[], int left, int mid, int right, int temp[]) {
        int i = left;
        int j = mid + 1;
        int t = 0;
        while (i <= mid && j <= right) {//将a数组分成两段,将对应位置值较小的放到temp数组
            if (a[i] <= a[j])
                temp[t++] = a[i++];
            else
                temp[t++] = a[j++];
        }
        while (i <= mid)//将剩下的放到temp数组
            temp[t++] = a[i++];
        while (j <= right)
            temp[t++] = a[j++];
        t = 0;
        int templeft = left;
        while (templeft <= right) {//将temp数组对应值放回a数组的对应位置
            a[templeft++] = temp[t++];
        }
    }//合并:a数组两半合并到新数组

public static void mergesort(int a[], int left, int right, int temp[]) {
        if (left < right) {
            int mid = (left + right) / 2;
            mergesort(a, left, mid, temp);//递归:分离原数组
            mergesort(a, mid + 1, right, temp);
            merge(a, left, mid, right, temp);//合并
        }
    }

  

快速排序

public static void quicksort_(int a[],int left,int right){
        if(left>right)
            return;
        int l=left;
        int r=right;
        int pivot=a[l];//将待排序值设置为最左值
        while (l<r){
            while (l<r&&a[r]>pivot)
                r--;
            a[l]=a[r];//右边选一个放到左边
            while (l<r&&a[l]<pivot)
                l++;
            a[r]=a[l];//左边选一个放到右边
        }
        a[l]=pivot;//空位置填上原值
        quicksort_(a,left,l-1);//左右递归
        quicksort_(a,l+1,right);
    }

基数排序

public static void radixsort_(int a[]) {
        int max = a[0];
        for (int i = 0; i < a.length; i++) {
            if (a[i] > max)
                max = a[i];
        }//获取最大值
        int maxlength = (max + "").length();//获取最大值的长度以便确定循环次数
        int[][] buket = new int[10][a.length];//定义桶(二维)
        int[] buketelementnum = new int[10];//每个桶中数的个数
        for (int i = 0, n = 1; i < maxlength; i++, n *= 10) {
            for (int j = 0; j < a.length; j++) {
                int temp = a[j] / n % 10;//获取数组每个元素的个/十/百..位
                buket[temp][buketelementnum[temp]++] = a[j];//加到桶里面
            }
            //桶中取出放回原数组
            int index = 0;
            for (int i1 = 0; i1 < 10; i1++) {
                if (buketelementnum[i1] != 0) {
                    for (int i2 = 0; i2 < buketelementnum[i1]; i2++) {
                        a[index++] = buket[i1][i2];
                    }
                }
                buketelementnum[i1] = 0;//清空桶中数据,方便下次放取
            }

        }
    }

堆排序

  • 处理局部
  • 转化成大顶堆/小顶堆
  • 将第一个和最后一个互换
 public static void adjust(int[] a, int i, int lenght) {
        int temp = a[i];
        for (int k = 2 * i + 1; k < lenght; k = 2 * k + 1) {
            if (k+1<lenght&&a[k] < a[k + 1]) {
                k++;
            }
            if (a[k] > temp) {
                a[i] = a[k];
                i = k;
            } else {
                break;
            }
        }
        a[i] = temp;
    }

    public static void heapsort_(int[] a) {
        int temp = 0;
        for (int i = a.length / 2 - 1; i >= 0; i--) {
            adjust(a, i, a.length);
        }
        for (int j = a.length - 1; j > 0; j--) {
            temp = a[0];
            a[0] = a[j];
            a[j] = temp;
            adjust(a, 0, j);
        }
    }

查找算法

二分查找

public static ArrayList binarysearch_(int[] a, int left, int right, int value) {//递归实现
        if (left > right)
            return new ArrayList();
        int mid = (left + right) / 2;
        int midvalue = a[mid];
        if (value > midvalue) {
            return binarysearch_(a, mid + 1, right, value);
        } else if (value < midvalue) {
            return binarysearch_(a, left, mid - 1, value);
        } else {
            ArrayList<Integer> integers = new ArrayList<>();
            int temp = mid - 1;
            while (true) {
                if (temp < 0 || a[temp] != value)
                    break;
                integers.add(temp);
                temp--;
            }
            integers.add(mid);
            temp=mid+1;
            while (true) {
                if (temp > a.length - 1 || a[temp] != value)
                    break;
                integers.add(temp);
                temp++;
            }
            return integers;
        }
    }
public static int binarysearch2(int arr[], int target) {//非递归
        int left = 0;
        int right = arr.length;
        while (left <=right) {
            int mid = (left + right) / 2;
            if (arr[mid] == target)
                return mid;
            else if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }

        }
        return -1;
    }

差值查找

 public static int insertvaluesearch_(int []a,int left,int right,int value){
        if(left>right||value<a[0]||value>a[a.length-1])
            return -1;
        int mid=left+(right-left)*(value-a[0])/(a[a.length-1]-a[0]);//设置插入值下标
        int midvalue=a[mid];
        if(value>midvalue)
            return insertvaluesearch_(a,mid+1,right,value);
        else if(value<midvalue)
            return insertvaluesearch_(a,left,mid-1,value);
        else
            return mid;
    }

哈希表

public class hashtab {
    public static void main(String[] args) {
        hashtab_ hashtab = new hashtab_(7);
        Scanner scanner = new Scanner(System.in);
        String key = " ";
        do {
            System.out.println("add :添加雇员");
            System.out.println("list:显示雇员");
            System.out.println("find:查找雇员");
            key = scanner.next();
            switch (key) {
                case "add":
                    System.out.println("请输入雇员id:");
                    int id = scanner.nextInt();
                    System.out.println("请输入雇员姓名:");
                    String name = scanner.next();
                    Emp emp = new Emp(id, name);
                    hashtab.add(emp);
                    break;
                case "list":
                    hashtab.list();
                    break;
                case "find":
                    System.out.println("请输入要查找对象的id号:");
                    id = scanner.nextInt();
                    hashtab.findbyid(id);
                default:
                    break;
            }
        } while (true);
    }
}

class Emp {
    private int id;
    private String name;
    public Emp next;

    public Emp(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

class EmpLinkedList {
    public Emp head;

    public void add(Emp a) {
        if (head == null) {
            head = a;
            return;
        }
        Emp temp = head;
        while (true) {
            if (temp.next == null)
                break;
            temp = temp.next;
        }
        temp.next = a;
    }

    public void list(int id) {
        if (head == null) {
            System.out.println("第" + (id + 1) + "条链表为空");
            return;
        }
        Emp temp = head;
        System.out.print("第" + (id + 1) + "条链表的信息为  ");
        while (true) {
            System.out.printf("id=%d , 姓名=%s ", temp.getId(), temp.getName());
            temp = temp.next;
            if (temp == null) {
                break;
            }
        }
        System.out.println();
    }

    public Emp findbyid(int id) {
        if (head == null)
            return null;
        Emp temp = head;
        while (true) {
            if (temp.getId() == id)
                break;
            if (temp.next == null) {
                temp = null;
                break;
            }
            temp = temp.next;
        }
        if (temp != null)
            return temp;
        else
            return null;
    }


}

class hashtab_ {
    private EmpLinkedList[] hashtab;
    private int size;

    public hashtab_(int size) {
        hashtab = new EmpLinkedList[size];
        this.size = size;
        for (int i = 0; i < size; i++) {
            hashtab[i] = new EmpLinkedList();
        }
    }

    public int gethashtabid(int id) {
        return id % size;
    }

    public void add(Emp a) {
        int no = gethashtabid(a.getId());
        hashtab[no].add(a);
    }

    public void list() {
        for (int i = 0; i < size; i++) {
            hashtab[i].list(i);
        }
    }

    public void findbyid(int id) {
        int no = gethashtabid(id);
        Emp findbyid = hashtab[no].findbyid(id);
        if(findbyid!=null)
            System.out.printf("该编号对应的名称为%s\n",findbyid.getName());
        else
            System.out.println("无法找到该编号");
    }
}

树的度:最大节点的度数

树转二叉树:第一个孩子在左边,兄弟在右边

树、森林、二叉树的转换

森林可没有树

正则二叉树:有子节点必有两个

二叉树

class BinaryTree {
	private HeroNode root;

	public void setRoot(HeroNode root) {
		this.root = root;
	}
	
	//删除结点
	public void delNode(int no) {
		if(root != null) {
			//如果只有一个root结点, 这里立即判断root是不是就是要删除结点
			if(root.getNo() == no) {
				root = null;
			} else {
				//递归删除
				root.delNode(no);
			}
		}else{
			System.out.println("空树,不能删除~");
		}
	}
	//前序遍历
	public void preOrder() {
		if(this.root != null) {
			this.root.preOrder();
		}else {
			System.out.println("二叉树为空,无法遍历");
		}
	}
	
	//中序遍历
	public void infixOrder() {
		if(this.root != null) {
			this.root.infixOrder();
		}else {
			System.out.println("二叉树为空,无法遍历");
		}
	}
	//后序遍历
	public void postOrder() {
		if(this.root != null) {
			this.root.postOrder();
		}else {
			System.out.println("二叉树为空,无法遍历");
		}
	}
	
	//前序遍历
	public HeroNode preOrderSearch(int no) {
		if(root != null) {
			return root.preOrderSearch(no);
		} else {
			return null;
		}
	}
	//中序遍历
	public HeroNode infixOrderSearch(int no) {
		if(root != null) {
			return root.infixOrderSearch(no);
		}else {
			return null;
		}
	}
	//后序遍历
	public HeroNode postOrderSearch(int no) {
		if(root != null) {
			return root.postOrderSearch(no);
		}else {
			return null;
		}
	}
}
class HeroNode {
	private int no;
	private String name;
	private HeroNode left; //默认null
	private HeroNode right; //默认null
	public HeroNode(int no, String name) {
		this.no = no;
		this.name = name;
	}

	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public HeroNode getLeft() {
		return left;
	}
	public void setLeft(HeroNode left) {
		this.left = left;
	}
	public HeroNode getRight() {
		return right;
	}
	public void setRight(HeroNode right) {
		this.right = right;
	}
	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + "]";
	}
	
	//递归删除结点
	//1.如果删除的节点是叶子节点,则删除该节点
	//2.如果删除的节点是非叶子节点,则删除该子树
	public void delNode(int no) {
		
		//思路
		/*
		 * 	1. 因为我们的二叉树是单向的,所以我们是判断当前结点的子结点是否需要删除结点,而不能去判断当前这个结点是不是需要删除结点.
			2. 如果当前结点的左子结点不为空,并且左子结点 就是要删除结点,就将this.left = null; 并且就返回(结束递归删除)
			3. 如果当前结点的右子结点不为空,并且右子结点 就是要删除结点,就将this.right= null ;并且就返回(结束递归删除)
			4. 如果第2和第3步没有删除结点,那么我们就需要向左子树进行递归删除
			5.  如果第4步也没有删除结点,则应当向右子树进行递归删除.

		 */
		//2. 如果当前结点的左子结点不为空,并且左子结点 就是要删除结点,就将this.left = null; 并且就返回(结束递归删除)
		if(this.left != null && this.left.no == no) {
			this.left = null;
			return;
		}
		//3.如果当前结点的右子结点不为空,并且右子结点 就是要删除结点,就将this.right= null ;并且就返回(结束递归删除)
		if(this.right != null && this.right.no == no) {
			this.right = null;
			return;
		}
		//4.我们就需要向左子树进行递归删除
		if(this.left != null) {
			this.left.delNode(no);
		}
		//5.则应当向右子树进行递归删除
		if(this.right != null) {
			this.right.delNode(no);
		}
	}
	
	//编写前序遍历的方法
	public void preOrder() {
		System.out.println(this); //先输出父结点
		//递归向左子树前序遍历
		if(this.left != null) {
			this.left.preOrder();
		}
		//递归向右子树前序遍历
		if(this.right != null) {
			this.right.preOrder();
		}
	}
	//中序遍历
	public void infixOrder() {
		
		//递归向左子树中序遍历
		if(this.left != null) {
			this.left.infixOrder();
		}
		//输出父结点
		System.out.println(this);
		//递归向右子树中序遍历
		if(this.right != null) {
			this.right.infixOrder();
		}
	}
	//后序遍历
	public void postOrder() {
		if(this.left != null) {
			this.left.postOrder();
		}
		if(this.right != null) {
			this.right.postOrder();
		}
		System.out.println(this);
	}
	
	//前序遍历查找
	/**
	 * 
	 * @param no 查找no
	 * @return 如果找到就返回该Node ,如果没有找到返回 null
	 */
	public HeroNode preOrderSearch(int no) {
		System.out.println("进入前序遍历");
		//比较当前结点是不是
		if(this.no == no) {
			return this;
		}
		//1.则判断当前结点的左子节点是否为空,如果不为空,则递归前序查找
		//2.如果左递归前序查找,找到结点,则返回
		HeroNode resNode = null;
		if(this.left != null) {
			resNode = this.left.preOrderSearch(no);
		}
		if(resNode != null) {//说明我们左子树找到
			return resNode;
		}
		//1.左递归前序查找,找到结点,则返回,否继续判断,
		//2.当前的结点的右子节点是否为空,如果不空,则继续向右递归前序查找
		if(this.right != null) {
			resNode = this.right.preOrderSearch(no);
		}
		return resNode;
	}
	
	//中序遍历查找
	public HeroNode infixOrderSearch(int no) {
		//判断当前结点的左子节点是否为空,如果不为空,则递归中序查找
		HeroNode resNode = null;
		if(this.left != null) {
			resNode = this.left.infixOrderSearch(no);
		}
		if(resNode != null) {
			return resNode;
		}
		System.out.println("进入中序查找");
		//如果找到,则返回,如果没有找到,就和当前结点比较,如果是则返回当前结点
		if(this.no == no) {
			return this;
		}
		//否则继续进行右递归的中序查找
		if(this.right != null) {
			resNode = this.right.infixOrderSearch(no);
		}
		return resNode;
		
	}
	
	//后序遍历查找
	public HeroNode postOrderSearch(int no) {
		
		//判断当前结点的左子节点是否为空,如果不为空,则递归后序查找
		HeroNode resNode = null;
		if(this.left != null) {
			resNode = this.left.postOrderSearch(no);
		}
		if(resNode != null) {//说明在左子树找到
			return resNode;
		}
		
		//如果左子树没有找到,则向右子树递归进行后序遍历查找
		if(this.right != null) {
			resNode = this.right.postOrderSearch(no);
		}
		if(resNode != null) {
			return resNode;
		}
		System.out.println("进入后序查找");
		//如果左右子树都没有找到,就比较当前结点是不是
		if(this.no == no) {
			return this;
		}
		return resNode;
	}
	
}

 二叉树遍历(非递归)

顺序存储二叉树

class ArrBinaryTree {
	private int[] arr;//存储数据结点的数组

	public ArrBinaryTree(int[] arr) {
		this.arr = arr;
	}
	
	//重载preOrder
	public void preOrder() {
		this.preOrder(0);
	}
	
	//编写一个方法,完成顺序存储二叉树的前序遍历
	/**
	 * 
	 * @param index 数组的下标 
	 */
	public void preOrder(int index) {
		//如果数组为空,或者 arr.length = 0
		if(arr == null || arr.length == 0) {
			System.out.println("数组为空,不能按照二叉树的前序遍历");
		}
		//输出当前这个元素
		System.out.println(arr[index]); 
		//向左递归遍历
		if((index * 2 + 1) < arr.length) {
			preOrder(2 * index + 1 );
		}
		//向右递归遍历
		if((index * 2 + 2) < arr.length) {
			preOrder(2 * index + 2);
		}
	}
	
}

线索化二叉树

class ThreadedBinaryTree {
    private HeroNode root;
    private HeroNode pre = null;

    public ThreadedBinaryTree(HeroNode root) {
        this.root = root;
    }

    public void threadedlist() {
        HeroNode node = root;
        while (node != null) {
            if (node.getLeftType() == 0)
                node = node.getLeft();
            System.out.println(node);
            while (node.getRightType() == 1) {
                node = node.getRight();
                System.out.println(node);
            }
            node = node.getRight();
        }
    }

    public void threadedNode(HeroNode node) {
        if (node == null)
            return;
        threadedNode(node.getLeft());
        if (node.getLeft() == null) {
            node.setLeft(pre);
            node.setLeftType(1);
        }
        if (pre != null && pre.getRight() == null) {
            pre.setRight(node);
            pre.setRightType(1);
        }
        pre = node;
        threadedNode(node.getRight());

    }

    public void PreOrder() {
        if (root != null) {
            root.PreOrder();
        } else {
            System.out.println("tree is empty");
        }
    }

    public void InfixOrder() {
        if (root != null) {
            root.InfixOrder();
        } else {
            System.out.println("tree is empty");
        }
    }

    public void PostOrder() {
        if (root != null) {
            root.PostOrder();
        } else {
            System.out.println("tree is empty");
        }
    }

    public HeroNode PreOrderSearch(int no) {
        if (root != null)
            return root.PreOrderSearch(no);
        else
            return null;
    }

    public void DelNode(int no) {
        if (root != null && root.getNo() != no) {
            root.DelNode(no);
        } else {
            root = null;
        }
    }
}

赫夫曼树

public static node createHuffmanTree(int[] a) {
        ArrayList<node> nodes = new ArrayList<>();
        for (int i : a) {
            node node = new node(i);
            nodes.add(node);
        }
        while (nodes.size() > 1) {
            Collections.sort(nodes);
            node leftnode = nodes.get(0);
            node rightnode = nodes.get(1);
            node newnode = new node(leftnode.getValue() + rightnode.getValue());
            newnode.setLeft(leftnode);
            newnode.setRight(rightnode);
            nodes.remove(leftnode);
            nodes.remove(rightnode);
            nodes.add(newnode);
            ;
        }
        return nodes.get(0);
    }

二叉排序树

树特点:左子叶值比当前结点小,右子叶值比当前结点大

class BinarySortTree_ {
    private Node root;

    public void add(Node node) {
        if (root == null) {
            root = node;
        } else {
            root.add(node);
        }
    }

    public void infixOrder() {
        if (root != null) {
            root.infixOrder();
        } else {
            System.out.println("二叉树空~");
        }
    }

    public Node getRoot() {
        return root;
    }

    public Node findNode(int value) {
        if (root == null) {
            return null;
        } else {
            return root.findNode(value);
        }
    }

    public Node findParent(int value) {
        if (root == null) {
            return null;
        } else {
            return root.findParent(value);
        }
    }

    public int delRightTreeMin(Node node) {
        Node target = node;
        while (target.getLeft() != null) {
            target = target.getLeft();
        }
        int value = target.getValue();
        delNode(target.getValue());
        return value;
    }

    public void delNode(int value) {
        if (root == null) {
            return;
        } else {
            Node targetnode = findNode(value);
            if (targetnode == null) {
                return;
            }
            if (root.getLeft() == null && root.getRight() == null) {
                root = null;
                return;
            }
            Node parent = findParent(value);
            if (targetnode.getLeft() == null && targetnode.getRight() == null) {
                if (parent.getLeft() != null && parent.getLeft().getValue() == value) {
                    parent.setLeft(null);
                } else if (parent.getRight() != null && parent.getRight().getValue() == value) {
                    parent.setRight(null);
                }
            } else if (targetnode.getLeft() != null && targetnode.getRight() != null) {
                int min = delRightTreeMin(targetnode);
                targetnode.setValue(min);
            } else {
                if (targetnode.getLeft() != null) {
                    if (parent != null) {
                        if (parent.getLeft() != null && parent.getLeft().getValue() == targetnode.getValue()) {
                            parent.setLeft(targetnode.getLeft());
                        } else if (parent.getRight() != null && parent.getRight().getValue() == value) {
                            parent.setRight(targetnode.getLeft());
                        }
                    } else {
                        root = targetnode.getLeft();
                    }
                } else {
                    if (parent != null) {
                        if (parent.getLeft().getValue() == value) {
                            parent.setLeft(targetnode.getRight());
                        } else {
                            parent.setRight(targetnode.getRight());
                        }
                    } else {
                        root = targetnode.getRight();
                    }
                }
            }
        }
    }
}

AVL树(平衡二叉树)

(双旋转)

class AVLTree_ {
    private Node root;

    public void add(Node node) {
        if (root == null) {
            root = node;
        } else {
            root.add(node);
        }
    }

    public void infixOrder() {
        if (root != null) {
            root.infixOrder();
        } else {
            System.out.println("二叉树空~");
        }
    }

    public Node getRoot() {
        return root;
    }

    public Node findNode(int value) {
        if (root == null) {
            return null;
        } else {
            return root.findNode(value);
        }
    }

    public Node findParent(int value) {
        if (root == null) {
            return null;
        } else {
            return root.findParent(value);
        }
    }

    public int delRightTreeMin(Node node) {
        Node target = node;
        while (target.getLeft() != null) {
            target = target.getLeft();
        }
        int value = target.getValue();
        delNode(target.getValue());
        return value;
    }

    public void delNode(int value) {
        if (root == null) {
            return;
        } else {
            Node targetnode = findNode(value);
            if (targetnode == null) {
                return;
            }
            if (root.getLeft() == null && root.getRight() == null) {
                root = null;
                return;
            }
            Node parent = findParent(value);
            if (targetnode.getLeft() == null && targetnode.getRight() == null) {
                if (parent.getLeft() != null && parent.getLeft().getValue() == value) {
                    parent.setLeft(null);
                } else if (parent.getRight() != null && parent.getRight().getValue() == value) {
                    parent.setRight(null);
                }
            } else if (targetnode.getLeft() != null && targetnode.getRight() != null) {
                int min = delRightTreeMin(targetnode);
                targetnode.setValue(min);
            } else {
                if (targetnode.getLeft() != null) {
                    if (parent != null) {
                        if (parent.getLeft() != null && parent.getLeft().getValue() == targetnode.getValue()) {
                            parent.setLeft(targetnode.getLeft());
                        } else if (parent.getRight() != null && parent.getRight().getValue() == value) {
                            parent.setRight(targetnode.getLeft());
                        }
                    } else {
                        root = targetnode.getLeft();
                    }
                } else {
                    if (parent != null) {
                        if (parent.getLeft().getValue() == value) {
                            parent.setLeft(targetnode.getRight());
                        } else {
                            parent.setRight(targetnode.getRight());
                        }
                    } else {
                        root = targetnode.getRight();
                    }
                }
            }
        }
    }
}

class Node {
    private int value;
    private Node left;
    private Node right;

    public int length() {
        return Math.max((left == null ? 0 : left.length()), (right == null ? 0 : right.length())) + 1;
    }

    public int leftlength() {
        if (left == null) {
            return 0;
        }
        return left.length();
    }

    public void leftrotate() {
        Node newnode = new Node(value);
        newnode.setLeft(left);
        newnode.setRight(right.getLeft());
        value = right.getValue();
        this.setRight(right.getRight());
        this.setLeft(newnode);
    }

    public void rightrotate() {
        Node newnode = new Node(value);
        newnode.setRight(right);
        newnode.setLeft(left.getRight());
        value = left.getValue();
        this.setLeft(left.getLeft());
        this.setRight(newnode);
    }

    public int rightlength() {
        if (right == null) {
            return 0;
        }
        return right.length();
    }

    public Node findNode(int value) {
        if (this.value == value) {
            return this;
        } else if (this.value > value) {
            if (this.getLeft() == null) {
                return null;
            }
            return this.left.findNode(value);
        } else {
            if (this.getRight() == null) {
                return null;
            }
            return this.right.findNode(value);
        }
    }

    public Node findParent(int value) {
        if ((this.left != null && this.left.getValue() == value) || (this.right.getValue() == value && this.right != null)) {
            return this;
        } else {
            if (value < this.getValue() && this.getLeft() != null) {
                return this.left.findParent(value);
            } else if (value >= this.getValue() && this.getRight() != null) {
                return this.right.findParent(value);
            } else {
                return null;
            }
        }
    }

    public void add(Node node) {
        if (node == null) {
            return;
        }
        if (node.getValue() < this.getValue()) {
            if (this.getLeft() == null) {
                this.setLeft(node);
            } else {
                this.getLeft().add(node);
            }
        } else {
            if (this.getRight() == null) {
                this.setRight(node);
            } else {
                this.getRight().add(node);
            }
        }
        if (rightlength() - leftlength() > 1) {
            if (right.leftlength() > right.rightlength() && right != null) {
                right.rightrotate();
                leftrotate();
            } else {
                leftrotate();
            }
        } else if (leftlength() - rightlength() > 1) {
            if (left.rightlength() > left.leftlength() && left != null) {
                left.leftrotate();
                rightrotate();
            } else {
                rightrotate();
            }
        }
    }

    public void infixOrder() {
        if (this.getLeft() != null) {
            this.getLeft().infixOrder();
        }
        System.out.println(this);
        if (this.getRight() != null) {
            this.getRight().infixOrder();
        }
    }

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

    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;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }
}

深度优先(dfs)

遍历邻接矩阵某行得到第一个结点的邻接结点的下标,若此下标存在且未被访问过,则递归dfs,访问过就求该结点的下一个邻接结点,重载dfs对每一个结点进行dfs

  public void dfs(boolean isvisited[], int i) {
        System.out.print(vertexlist.get(i) + " ");
        isvisited[i] = true;
        int w = getfirstlinkedindex(i);
        while (w != -1) {
            if (!isvisited[w]) {
                dfs(isvisited, w);
            }
            w = getnextlinkedindex(i, w);

        }
    }

    public void dfs() {
        for (int i1 = 0; i1 < vertexlist.size(); i1++) {
            if (!isvisited[i1]) {
                dfs(isvisited, i1);
            }
        }
    }

广度优先(bfs)

public void bfs(boolean isvisited[], int i) {
        int u;
        int w;
        LinkedList<Integer> queue = new LinkedList<>();
        System.out.print(getvaluebyid(i) + " ");
        isvisited[i] = true;
        queue.addLast(i);
        while (!queue.isEmpty()) {
            u = queue.removeFirst();
            w = getfirstlinkedindex(u);
            if (w != -1) {
                if (!isvisited[w]) {
                    System.out.print(getvaluebyid(w) + " ");
                    isvisited[w] = true;
                    queue.addLast(w);
                }
                w = getnextlinkedindex(u, w);
            }
        }
    }

    public void bfs() {
        for (int i = 0; i < getvertexnum(); i++) {
            if (!isvisited[i]) {
                bfs(isvisited, i);
            }
        }
    }

分治算法

动态规划

public class _01bag {//例:01背包
    public static void main(String[] args) {
        int w[] = {0, 1, 4, 3};
        int val[] = {0, 1500, 3000, 2000};
        int n = w.length - 1;//物品个数
        int vec = 4;//背包容量
        int[][] v = new int[n + 1][vec + 1];
        int[][] path = new int[n + 1][vec + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= vec; j++) {
                if (w[i] > j) {
                    v[i][j] = v[i - 1][j];
                } else {
                    if (v[i - 1][j] > val[i] + v[i - 1][j - w[i]]) {
                        v[i][j] = v[i - 1][j];
                    } else {
                        v[i][j] = val[i] + v[i - 1][j - w[i]];
                        path[i][j] = 1;
                    }
                }
            }
        }
        for (int[] ints : v) {
            for (int anInt : ints) {
                System.out.print(anInt + " ");
            }
            System.out.println();
        }
        int i = n;
        int j = vec;
        while (i > 0 && j > 0) {
            if (path[i][j] == 1) {
                System.out.printf("第%d个物品放入背包 ", i);
                j -= w[i];
            }
            i--;
        }
    }
}

KMP算法(字符串匹配问题)

步骤: 

  1. 获得字句的部分匹配值表(关于部分匹配值表的详细介绍可参考很详尽KMP算法(厉害) - ZzUuOo666 - 博客园
  2. kmp搜索
    public static int[] kmpNext(String dest){//步骤1:获取部分匹配值数组next
            int[] next=new int[dest.length()];
            next[0]=0;
            for (int i = 1,j=0; i <dest.length() ; i++) {
                while(j>0&&dest.charAt(i)!=dest.charAt(j)){
                    j= next[j-1];//核心代码
                }
                if(dest.charAt(i)==dest.charAt(j)){//若出现重复,则匹配值(j)++
                    j++;
                }
                next[i]=j;
            }
            return next;
        }
        public static int KMPsearch(String s1,String s2,int[] next){//步骤2:KMP算法
            for(int i=0,j=0;i<s1.length();i++){
                while(j>0&&s1.charAt(i)!=s2.charAt(j)){
                    j= next[j-1];//核心代码
                }
                if(s1.charAt(i)==s2.charAt(j)){//当字符匹配时j++
                    j++;
                }
    
                if(j==s2.length()){//j=子句长度,说明存在这样的子句,返回下标
                    return i-j+1;
                }
            }
            return -1;
        }

    贪心算法

  • 例题:

思路:

public class greedyAlgorithm {
    public static void main(String[] args) {
        //创建广播电台,放入到Map
        HashMap<String, HashSet<String>> broadcasts = new HashMap<String, HashSet<String>>();
        //将各个电台放入到broadcasts
        HashSet<String> hashSet1 = new HashSet<String>();
        hashSet1.add("北京");
        hashSet1.add("上海");
        hashSet1.add("天津");

        HashSet<String> hashSet2 = new HashSet<String>();
        hashSet2.add("广州");
        hashSet2.add("北京");
        hashSet2.add("深圳");

        HashSet<String> hashSet3 = new HashSet<String>();
        hashSet3.add("成都");
        hashSet3.add("上海");
        hashSet3.add("杭州");


        HashSet<String> hashSet4 = new HashSet<String>();
        hashSet4.add("上海");
        hashSet4.add("天津");

        HashSet<String> hashSet5 = new HashSet<String>();
        hashSet5.add("杭州");
        hashSet5.add("大连");

        //加入到map
        broadcasts.put("K1", hashSet1);
        broadcasts.put("K2", hashSet2);
        broadcasts.put("K3", hashSet3);
        broadcasts.put("K4", hashSet4);
        broadcasts.put("K5", hashSet5);

        //allAreas 存放所有的地区
        HashSet<String> allAreas = new HashSet<String>();
        allAreas.add("北京");
        allAreas.add("上海");
        allAreas.add("天津");
        allAreas.add("广州");
        allAreas.add("深圳");
        allAreas.add("成都");
        allAreas.add("杭州");
        allAreas.add("大连");
        HashSet<String> temp = new HashSet<>();//用于求覆盖的城市(交运算)
        HashSet<String> selected = new HashSet<>();//存放选出的广播台
        String Maxkey = null;
        while (allAreas.size() != 0) {
            Maxkey = null;    //清空指针
            for (String key : broadcasts.keySet()) {
                temp.clear();
                temp.addAll(broadcasts.get(key));
                temp.retainAll(allAreas);
                if (temp.size() > 0 && (Maxkey == null || temp.size() > broadcasts.get(Maxkey).size())) {    
//核心:最大指针为空或者该广播台覆盖的未覆盖城市大于当前指针指向广播台数目,则更改指向
                    Maxkey = key;
                }
            }
            if (Maxkey != null) {    //清完一轮后,选择广播台并清空对应城市
                selected.add(Maxkey);
                allAreas.removeAll(broadcasts.get(Maxkey));
            }
        }
        System.out.println("selected=" + selected);

    }
}

普里姆算法(最小生成树)

例题(修路问题):

public class Prim {
    public static void main(String[] args) {
        char[] data = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int verxs = data.length;
        //邻接矩阵的关系使用二维数组表示,10000这个大数,表示两个点不联通
        int[][] weight = new int[][]{
                {10000, 5, 7, 10000, 10000, 10000, 2},
                {5, 10000, 10000, 9, 10000, 10000, 3},
                {7, 10000, 10000, 10000, 8, 10000, 10000},
                {10000, 9, 10000, 10000, 10000, 4, 10000},
                {10000, 10000, 8, 10000, 10000, 5, 4},
                {10000, 10000, 10000, 4, 5, 10000, 6},
                {2, 3, 10000, 10000, 4, 6, 10000},};
        MGragh mGragh = new MGragh(data.length);
        MinTree minTree = new MinTree();
        minTree.createGragh(mGragh, verxs, data, weight);
        minTree.prim(mGragh, 0);

    }
}

class MinTree {//最小生成树类
    public void createGragh(MGragh gragh, int vetexs, char[] data, int[][] weight) {
                //创建图
        for (int i = 0; i < vetexs; i++) {
            gragh.data[i] = data[i];
            for (int j = 0; j < vetexs; j++) {
                gragh.weight[i][j] = weight[i][j];
            }
        }
    }

    void prim(MGragh gragh, int v) {//核心代码
        int[] visited = new int[gragh.vetexs];
        int minvalue = 10000;
        visited[v] = 1;//标记已访问
        int n1 = -1, n2 = -1;
        for (int k = 0; k < gragh.vetexs - 1; k++) {//共修建n-1条边
            for (int i = 0; i < gragh.vetexs; i++) {//已访问结点
                for (int j = 0; j < gragh.vetexs; j++) {//未访问结点
                    if (visited[i] == 1 && visited[j] == 0 && gragh.weight[i][j] < minvalue) {//寻找权值最小的边
                        n1 = i;
                        n2 = j;
                        minvalue = gragh.weight[i][j];
                    }
                }
            }
            System.out.println("边<" + gragh.data[n1] + "," + gragh.data[n2] + "> 权值:" + minvalue);
            minvalue = 10000;//重置为一个不可能最小的数
            visited[n2] = 1;//把刚刚未访问的也标记为访问
        }
    }
}

class MGragh {//图形类
    int vetexs;
    char[] data;
    int[][] weight;

    public MGragh(int vetexs) {
        this.vetexs = vetexs;
        data = new char[vetexs];
        weight = new int[vetexs][vetexs];
    }
}

克鲁斯卡尔算法(最小生成树)

例题:

 

 

加入边的两个顶点不能指向同一个终点,否则构成回路

public class kruskalAlgorithm {
    private char[] vertexs;//存符号
    private int matrix[][];//邻接矩阵
    private int edgenum;//边的个数
    private static int INF = Integer.MAX_VALUE;

    public static void main(String[] args) {

        char[] vertexs = {'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}};
        kruskalAlgorithm kruskal = new kruskalAlgorithm(vertexs, matrix);
        kruskal.kruskalalgorithm(vertexs,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(matrix[i][j]!=INF){
                    edgenum++;
                }
            }
        }

    }

    public edges[] Getedges(int[][] matrix) {//获取所有的边
        int index = 0;
        edges[] edges = new edges[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 edges(vertexs[i], vertexs[j], matrix[i][j]);
                }
            }
        }
        return edges;
    }

    public void sortedges(edges[] ed) {//对边按权值的大小从小到大排序
        for (int i = 0; i < ed.length - 1; i++) {
            for (int j = 0; j < ed.length - 1 - i; j++) {
                if (ed[j+1].value < ed[j].value) {
                    edges e = ed[j+1];
                    ed[j+1] = ed[j];
                    ed[j] = e;
                }
            }
        }
    }

    public int Getindex(char x) {//求出字符的对应下标
        for (int i = 0; i < vertexs.length; i++) {
            if (vertexs[i] == x) {
                return i;
            }
        }
        return -1;
    }

    public int Getend(int ends[], int i) {//获取下标为i的元素对应终点的下标
        while (ends[i] != 0) {//核心代码:ends是动态变化的
            i = ends[i];
        }
        return i;
    }

    public void kruskalalgorithm(char[] vertexs, int matrix[][]) {//核心代码:克鲁斯卡尔算法
        edges[] edges = Getedges(matrix);
        edges[] res = new edges[edgenum];
        sortedges(edges);
        int index=0;
        int[] ends = new int[edgenum];
        for (int i = 0; i < edges.length; i++) {
            char p1=edges[i].start;
            char p2=edges[i].end;
            if(Getend(ends,Getindex(p1))!=Getend(ends,Getindex(p2))){    //若两个顶点的终点不一致,则将第一个点的终点设置为第二个点的终点
                ends[Getend(ends,Getindex(p1))]=Getend(ends,Getindex(p2));
                res[index++]=edges[i];
            }
        }
        //打印最小生成树
        for (int i = 0; i <index ; i++) {
            System.out.println(res[i]);
        }
    }
}

class edges {
    public char start;
    public char end;
    public int value;

    public edges(char start, char end, int value) {
        this.start = start;
        this.end = end;
        this.value = value;
    }

    @Override
    public String toString() {
        return "edges{" +
                "start=" + start +
                ", end=" + end +
                ", value=" + value +
                '}';
    }
}

Dijkstra算法(一点的最短路径)

 

建立两个类:

Visitedvertex(判断已访问数组,前驱结点数组,距离数组)

Gragh(顶点数组,关系矩阵,Visitedvertex)

核心:

更新index周围顶点的距离和前驱结点,并对每个顶点操作一次(广度优先

public class djs {
    public static void main(String[] args) {
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        //邻接矩阵
        int[][] matrix = new int[vertex.length][vertex.length];
        final int N = 65535;// 表示不可以连接
        matrix[0] = new int[]{N, 5, 7, N, N, N, 2};
        matrix[1] = new int[]{5, N, N, 9, N, N, 3};
        matrix[2] = new int[]{7, N, N, N, 8, N, N};
        matrix[3] = new int[]{N, 9, N, N, N, 4, N};
        matrix[4] = new int[]{N, N, 8, N, N, 5, 4};
        matrix[5] = new int[]{N, N, N, 4, 5, N, 6};
        matrix[6] = new int[]{2, 3, N, N, 4, 6, N};
        Gragh gragh = new Gragh(vertex, matrix, vertex.length - 1);
        gragh.djs(vertex.length - 1);
        System.out.println(Arrays.toString(gragh.vv.already_arr));
        System.out.println(Arrays.toString(gragh.vv.pre_visited));
        System.out.println(Arrays.toString(gragh.vv.dis));

    }
}

class Gragh {
    public char[] vertex;//顶点数组
    public int[][] matrix;//矩阵
    VisitedVertex vv;

    public Gragh(char[] vertex, int[][] matrix, int index) {
        this.vertex = vertex;
        this.matrix = matrix;
        vv = new VisitedVertex(index, vertex.length);
    }

    public void update(int index) {//更新index周围顶点的距离和前驱节点
        for (int i = 0; i < matrix[index].length; i++) {
            int len = matrix[index][i] + vv.dis[index];
            if (vv.dis[i] > len) {
                vv.dis[i] = len;
                vv.updatepre(i, index);
            }
        }
    }

    public void djs(int index) {//核心:更新每个顶点(bfs)
        update(index);
        for (int i = 1; i < vertex.length; i++) {
            int j = vv.updateArr();
            update(j);
        }
    }
}

class VisitedVertex {
    public int[] already_arr;//已访问数组(若访问则下标=1)
    public int[] pre_visited;//前驱节点数组
    public int[] dis;//距离数组

    public VisitedVertex(int index, int length) {
        already_arr = new int[length];
        pre_visited = new int[length];
        dis = new int[length];
        already_arr[index] = 1;
        Arrays.fill(dis, 65535);
        dis[index] = 0;
    }

    public boolean in(int index) {//判断是否访问过
        return already_arr[index] == 1;
    }

    public void updatedis(int index, int len) {//更新距离
        dis[index] = len;
    }

    public int getdis(int index) {//获得距离
        return dis[index];
    }

    public void updatepre(int index, int pre) {//更新前驱节点
        pre_visited[index] = pre;
    }

    public int updateArr() {//获取下一个更新的顶点下标(按离出发顶点的距离递增求)
        int min = 65535, index = 0;
        for (int i = 0; i < dis.length; i++) {
            if (already_arr[i] == 0 && dis[i] < min) {
                min = dis[i];
                index = i;
            }
        }
        already_arr[index] = 1;
        return index;
    }
}

弗洛伊德算法(任意点的最短路径)

 

 (三层for循环,针对每个中心节点,求任意点间最小距离,最后距离矩阵就是对应的点间最小值)

public class FloydAlgorithm {
    public static void main(String[] args) {
        char[] vertex = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
        //创建邻接矩阵
        int[][] matrix = new int[vertex.length][vertex.length];
        final int N = 65535;
        matrix[0] = new int[] { 0, 5, 7, N, N, N, 2 };
        matrix[1] = new int[] { 5, 0, N, 9, N, N, 3 };
        matrix[2] = new int[] { 7, N, 0, N, 8, N, N };
        matrix[3] = new int[] { N, 9, N, 0, N, 4, N };
        matrix[4] = new int[] { N, N, 8, N, 0, 5, 4 };
        matrix[5] = new int[] { N, N, N, 4, 5, 0, 6 };
        matrix[6] = new int[] { 2, 3, N, N, 4, 6, 0 };
        Graph graph = new Graph(vertex.length, vertex, matrix);
        graph.Floyd();
        System.out.println("A和C的最短距离为"+graph.dis[0][2]);
    }

}
class Graph{
    char[] vertex;
    int [][] dis;//距离矩阵
    int [][] pre;//前驱节点矩阵
    public Graph(int lenght,char[] vertex,int [][] matrix){
        this.vertex=vertex;
        this.dis=matrix;
        pre=new int[lenght][lenght];
        for(int i=0;i<vertex.length;i++){
            Arrays.fill(pre[i],i);
        }
    }
    public void Floyd(){
        for(int k=0;k<vertex.length;k++){//中心节点
            int len=0;
            for(int i=0;i<vertex.length;i++){//出发顶点
                for(int j=0;j<vertex.length;j++){//结束顶点
                    len=dis[i][k]+dis[k][j];
                    if(len<dis[i][j]){
                        dis[i][j]=len;//更新距离
                        pre[i][j]= pre[k][j];//更新前驱节点
                    }
                }
            }
        }
    }
}

 马踏棋盘算法(dfs)

 

public class Chesstravel {
    private static int X = 6;
    private static int Y = 6;
    private static boolean[][] visited = new boolean[X][Y];
    private static boolean finished;

    public static void main(String[] args) {
        int[][] Chess = new int[X][Y];
        HorseChessBoard(Chess, 1, 4, 1);
        for (int[] chess : Chess) {
            System.out.println(Arrays.toString(chess));
        }
    }

    public static void HorseChessBoard(int[][] Chess, int col, int row, int step) {//dfs
        visited[row][col] = true;
        Chess[row][col] = step;
        ArrayList<Point> parr = next(new Point(row, col));//获取当前点的下一步
        parr.sort(new Comparator<Point>() {//将下一步顶点按该点下一步顶点个数排序(优化)
            @Override
            public int compare(Point o1, Point o2) {
                if (next(o1).size() < next(o1).size()) {
                    return -1;
                } else if (next(o1).size() > next(o1).size()) {
                    return 1;
                } else
                    return 0;
            }
        });
        while (!parr.isEmpty()) {
            Point p = parr.remove(0);//取出的第一个点,如果没被访问过就递归
            if (!visited[p.x][p.y])//没访问过就递归:体现dfs
                HorseChessBoard(Chess, p.y, p.x, step + 1);
        }
        if (step < X * Y && !finished) {//没走完就重置
            visited[row][col] = false;
            Chess[row][col] = 0;
        } else {//走完了就将finished置为true
            finished = true;
        }
    }


    public static ArrayList<Point> next(Point a) {//获取当前顶点的可能下一步(放到集合 )
        ArrayList<Point> ps = new ArrayList<>();
        Point point = new Point();
        if ((point.x = a.x + 1) < X && (point.y = a.y + 2) < Y) {
            ps.add(new Point(point));
        }
        if ((point.x = a.x + 2) < X && (point.y = a.y + 1) < Y) {
            ps.add(new Point(point));
        }
        if ((point.x = a.x + 2) < X && (point.y = a.y - 1) >= 0) {
            ps.add(new Point(point));
        }
        if ((point.x = a.x + 1) < X && (point.y = a.y - 2) >= 0) {
            ps.add(new Point(point));
        }
        if ((point.x = a.x - 1) >= 0 && (point.y = a.y - 2) >= 0) {
            ps.add(new Point(point));
        }
        if ((point.x = a.x - 2) >= 0 && (point.y = a.y - 1) >= 0) {
            ps.add(new Point(point));
        }
        if ((point.x = a.x - 2) >= 0 && (point.y = a.y + 1) < Y) {
            ps.add(new Point(point));
        }
        if ((point.x = a.x - 1) >= 0 && (point.y = a.y + 2) < Y) {
            ps.add(new Point(point));
        }
        return ps;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值