算法和数据结构-基础

本文介绍了数据结构中的线性结构(如数组、队列、链表和栈)和非线性结构(如二维数组、多维数组、广义表、树结构和图结构),详细讲解了稀疏数组的转换和恢复,以及队列的实现。此外,还涉及了链表(单链表和双向链表)的基本操作,栈的入栈和出栈原理,以及排序算法(冒泡排序、选择排序、插入排序和基数排序)和查找算法(二分查找和插值查找)。
摘要由CSDN通过智能技术生成

算法和数据结构

数据结构

数据结构包括线性结构和非线性结构

线性结构常见的有:数组、队列、链表和栈

  • 线性元素特点是一对一
  • 线性结构有顺序存储结构(数组)和链式存储结构(链表)

非线性结构包括:二维数组,多维数组,广义表,树结构,图结构

稀疏数组

首行记录:一个数记录表有多少行,第二行记录表有列,第三行记录表有多少有效数据

需求:棋盘或地图(保存棋盘)达到压缩的效果

代码实现:

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;
    // 原始二维数组
    for (int i = 0; i < chessArr1.length; i++) {
        System.out.println(Arrays.toString(chessArr1[i]));
    }

    // 将二维数组 转为 稀疏数组
    // 先循环 获取到非0数据的个数
    int sum = 0;
    for (int i = 0; i < chessArr1.length; i++) {
        for (int j = 0; j < chessArr1[i].length; j++) {
            if(chessArr1[i][j] != 0){
                sum++;
            }
        }
    }
    System.out.println("总共有效数据,sum:"+sum);

    // 可以创建稀疏数组   稀疏数组第一列
    int[][] sparseArr = new int[sum+1][3];
    // 给稀疏数组赋值
    sparseArr[0][0] = chessArr1[0].length;
    sparseArr[0][1] = chessArr1.length;
    sparseArr[0][2] = sum;
    int count = 0;
    for (int i = 0; i < chessArr1.length; i++) {
        for (int j = 0; j < chessArr1[i].length; j++) {
            if(chessArr1[i][j] != 0){
                count++;
                sparseArr[count][0] = i;
                sparseArr[count][1] = j;
                sparseArr[count][2] = chessArr1[i][j];
            }
        }
    }

    // 输出稀疏数组
    System.out.println("稀疏数组为:");
    for (int i = 0; i < sum+1; i++) {
        System.out.println(Arrays.toString(sparseArr[i]));
    }


    // 恢复成原本的二维数组
    // 1.先读取稀疏数组第一行数据
    // 二维数组原本的行数
    int row =sparseArr[0][0];
    // 二维数组原本的列数
    int column =sparseArr[0][1];
    // 有效数据的个数
    int data = sparseArr[0][2];
    int[][] chessArr2 =new int[row][column] ;

    // 不是从首行开始,首行是记录表的整体数据,所以从1开始
    // 开始还原二维数组
    for (int i = 1; i < data+1; i++) {
        int rowArr = sparseArr[i][0];
        int columnArr = sparseArr[i][1];
        int num = sparseArr[i][2];
        chessArr2[rowArr][columnArr]=num;
    }

    System.out.println("还原结果:");

    for (int i = 0; i < chessArr2.length; i++) {
        System.out.println(Arrays.toString(chessArr2[i]));
    }

}

队列

在这里插入图片描述

⭐️是一个有序列表,可以用数组或链表来实现。

原则:先入先出

在这里插入图片描述

思路:

在这里插入图片描述

代码实现:

class CircleArrayQueue{
    private int maxSize;// 最大容量
    // front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
    // front 的初始值 = 0
    private int front;
    // rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定. //rear 的初始值 = 0
    private int rear; // 队列尾

    private int[] arr; // 该数据用于存放数据

    public CircleArrayQueue(int arrMaxSize){
        maxSize =arrMaxSize;
        this.arr = new int[maxSize];
        this.front = 0;
        this.rear = 0;//!指向队列尾,指向队列尾的数据(即就是队列最一个数据)
    }

    // 判断队列是否满
    public boolean isQueueFull(){
        return (rear+1)%maxSize == front;
    }
    // 判断队列是否为空
    public boolean isEmpty(){
        return front == rear;
    }

    // 添加数据到队列
    public void addQueue(int num){
        // 判断队列是否满
        if(isQueueFull()){
            System.out.println("队列已满,无法添加");
            return;
        }
        arr[rear] = num;
        // 将 rear 后移, 这里必须考虑取模
        rear = (rear+1) % maxSize;
        return ;
    }
    // 获取队列的数据,出队列
    public int popQueue(){
        // 判断队列是否为空
        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开始遍历,遍历多少个元素
        int number = (rear + maxSize - front)%maxSize;

        for (int i = front; i < front + number; i++) {
            System.out.println("arr["+i % maxSize+"]="+arr[i % maxSize]);

        }
    }


    // 显示队列的头数据,不是取出只是显示
    public int headQueue(){
        // 判断队列是否满
        if(isEmpty()){
            throw new RuntimeException("队列空的,没有数据");
        }

        return arr[front];
    }
}

单链表(链表Linked List)

在这里插入图片描述

链表是有序的列表

每个节点

  • 有个==data==属性来存放数据
  • 有个next属性存放下一个节点

节点存放的下一个数据, 不是 连续存放的

在这里插入图片描述

思路:

在这里插入图片描述

代码实现:

// 单链表的的节点属性
class SingLinkedListNode{

    // 当前存储的数据,就存放int数据类型(也可以改成类来存放)
    public int data;
    // 指向下一个节点
    SingLinkedListNode next;

    // 构造器
    public SingLinkedListNode(int data){
        this.data = data;
    }

    // 为了显示方法,重写toString
    @Override
    public String toString() {
        return "SingLinkedListNode{" +
                ", no=" + data +
                '}';
    }
}
// 单链表
class SingLinkedList{
    // 初始化一个头节点,头节点不动,不存放具体数据
    private SingLinkedListNode head = new SingLinkedListNode(0);

    // 添加节点
    // 思路,当不考虑编号顺序时
    // 1.当前链表的最后节点
    // 2.将最后这个节点的next指向 新的节点
    public void add(SingLinkedListNode singLinkedListNode){
        // 因为head节点不能动
        // 要有一个辅助指针遍历单链表
        // 因为单链表,因为我们找的temp是位于添加位置的前一个节点,否则插入不了
        SingLinkedListNode temp =  head;
        boolean flag = false; // 标志添加的编号是否存在,默认为false
        while (true){
            // 找到最后一个节点
            if(temp.next == null){
                // 指向新的节点
                break;
            }

            // 找到这个位置就可以插入
            if(temp.next.data > singLinkedListNode.data){
                break;
            }else if(temp.next.data == singLinkedListNode.data){
                // 说明该数据已经有了
                flag = true;
                break;
            }

            // 没找到辅助指针 往下找
            temp = temp.next;
        }

        if(flag){
            // 不能添加,编号已经存在
            System.out.println("插入的数据,已经存在了");
            return;
        }

        // 插入到链表中,temp的后面
        singLinkedListNode.next = temp.next;
        temp.next = singLinkedListNode;
    }



    // 显示链表 遍历
    public void list(){
        // 判断链表是否为空
        if(head.next == null){
            System.out.println("链表为空~");
            return;
        }

        // 因为头节点,不能动,因此我们需要一个辅助变量
        SingLinkedListNode temp = head.next;
        while(true){
            // 判断链表是否到 最后了
            if(temp == null){
                break;
            }

            // 输出节点信息
            System.out.println(temp);
            // 移动到下一位
            temp = temp.next;
        }
    }

    //修改节点信息,根据data信息,修改data
    public void update(SingLinkedListNode oldNode,SingLinkedListNode newNode){
        // 判断是否为空
        if(head.next == null){
            System.out.println("链表为空!");
            return;
        }
        // 要有一个辅助指针遍历单链表
        SingLinkedListNode temp =  head;
        boolean flag =false; // 表示是是否找到该节点
        while(true){
            if(temp == null){
                break;// 已经遍历完
            }
            if(temp.data == oldNode.data){
                // 找到
                flag = true;
                break;
            }
        }

        if(flag){
            temp.data = newNode.data;
        }else{
            // 没有找到
            System.out.println("没有找到编号为:"+oldNode.data);
        }



    }
}

双向链表

在这里插入图片描述

对上图的说明:

分析 双向链表的遍历,添加,修改,删除的操作思路===》代码实现

  1. 遍历 方和 单链表一样,只是可以向前,也可以向后查找

  2. 添加 (默认添加到双向链表的最后)

(1) 先找到双向链表的最后这个节点

​ (2) temp.next = newHeroNode

​ (3) newHeroNode.pre = temp;

  1. 修改 思路和 原来的单向链表一样.

  2. 删除

    (1) 因为是双向链表,因此,我们可以实现自我删除某个节点

​ (2) 直接找到要删除的这个节点,比如 temp

​ (3) temp.pre.next = temp.next

​ (4) temp.next.pre = temp.pre

// 创建一个双向链表的类
class DoubleLinkedList {
	// 先初始化一个头节点, 头节点不要动, 不存放具体的数据
	private HeroNode2 head = new HeroNode2(0, "", "");
	// 返回头节点
    public HeroNode2 getHead() {
        return head;
    }
    // 遍历双向链表的方法
    // 显示链表[遍历]
    public void list() {
        // 判断链表是否为空
        if (head.next == null) {
        	System.out.println("链表为空");
        	return;
        }
        
        // 因为头节点,不能动,因此我们需要一个辅助变量来遍历
        HeroNode2 temp = head.next;
        while (true) {
            // 判断是否到链表最后
            if (temp == null) {
            break;
        }
            
        // 输出节点的信息
        System.out.println(temp);
        // 将 temp 后移, 一定小心
        temp = temp.next;
        }
    }
	// 添加一个节点到双向链表的最后.
    public void add(HeroNode2 heroNode) {
    // 因为 head 节点不能动,因此我们需要一个辅助遍历 temp
    HeroNode2 temp = head;
        
    // 遍历链表,找到最后
    while (true) {
        // 找到链表的最后
        if (temp.next == null) {//
    	break;
   		}
	    // 如果没有找到最后, 将将 temp 后
        temp = temp.next;
    }
        
    // 当退出 while 循环时,temp 就指向了链表的最后
    // 形成一个双向链表
    temp.next = heroNode;
    heroNode.pre = temp;
}
// 修改一个节点的内容, 可以看到双向链表的节点内容修改和单向链表一样
// 只是 节点类型改成 HeroNode2
public void update(HeroNode2 newHeroNode) {
    // 判断是否空
    if (head.next == null) {
        System.out.println("链表为空~");
        return;
    }
    // 找到需要修改的节点, 根据 no 编号
    // 定义一个辅助变量
    HeroNode2 temp = head.next;
    boolean flag = false; // 表示是否找到该节点
    while (true) {
        if (temp == null) {
            break; // 已经遍历完链表
        }
        if (temp.no == newHeroNode.no) {
        // 找到
        flag = true;
        break;
        }
    	temp = temp.next;
    }
    
    // 根据 flag 判断是否找到要修改的节点
    if (flag) {
        temp.name = newHeroNode.name;
        temp.nickname = newHeroNode.nickname;
    } else { // 没有找到
    	System.out.printf("没有找到 编号 %d 的节点,不能修改\n", newHeroNode.no);
    }
}

// 从双向链表中删除一个节点, // 说明
// 1 对于双向链表,我们可以直接找到要删除的这个节点
// 2 找到后,自我删除即可
public void del(int no) {
    // 判断当前链表是否为空
    if (head.next == null) {// 空链表
        System.out.println("链表为空,无法删除");
        return;
    }
    HeroNode2 temp = head.next; // 辅助变量(指针)
    boolean flag = false; // 标志是否找到待删除节点的
    
    while (true) {
        if (temp == null) { // 已经到链表的最后
        break;
    }
    if (temp.no == no) {
        // 找到的待删除节点的前一个节点 temp
        flag = true;
    	break;
    }
    temp = temp.next; // temp 后移,遍历
    }
}


栈(stack)

特性: 先入后出

是先入后出的有序列表,栈底不变,变化的一端为栈顶

出栈(pop) 入栈(push)

在这里插入图片描述
在这里插入图片描述

思路:
在这里插入图片描述

代码实现(数组模拟):

// 定义一个ArrayStack 表示栈
class ArrayStack{
    private int maxSize;// 栈的大小
    private int[] stack;// 数组,数组模拟栈,数据就放在该数组
    private int top = -1;// top表示栈顶,初始化为-1

    // 构造器
    public ArrayStack(int maxSize){
        this.maxSize = maxSize;
        stack = new int[this.maxSize];
    }

    // 栈满
    public boolean isFull(){
        return top == this.maxSize-1;
    }
    // 栈空
    public boolean isEmpty(){
        return top == -1;
    }
    // 入栈
    public void push(int data){
        // 判断是否满
        if(isFull()){
            System.out.println("栈已满,无法放");
            return;
        }
        stack[++top] = data;
    }
    // 出栈
    public int pop(){
        if(isEmpty()){
            System.out.println("空的,没有数据");
            return -1;
        }
        int value = stack[top];
        top-- ;
        return value;
    }
    // 显示栈的情况(遍历栈),遍历时,需要从栈顶开始显示
    public void print(){
        if(isEmpty()){
            System.out.println("栈空,没有数据");
            return;
        }
        // 需要从栈顶开始显示
        for (int i = top; i >= 0 ; i--) {
            System.out.println("stack["+top+"]="+stack[top]);
        }

    }

}

算法

算法的时间复杂度

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

递归

在这里插入图片描述

简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时 可以让代码变得简洁。
public static void main(String[] args) {
        // TODO Auto-generated method stub
        //通过打印问题,回顾递归调用机制
        //test(4);
        int res = factorial(3);
        System.out.println("res=" + res);
    }

    //打印问题.
    public static void test(int n) {
        if (n > 2) {
            test(n - 1);
        } //else {
        System.out.println("n=" + n);
        // }
    }

    //阶乘问题
    public static int factorial(int n) {
        if (n == 1) {
            return 1;
        } else {
            return factorial(n - 1) * n; // 1 * 2 * 3
        }
    }

排序算法

在这里插入图片描述
在这里插入图片描述

冒泡排序(BubbleSort)

时间复杂度O(n2)

在这里插入图片描述

代码实现

public static void main(String[] args) {
    int[] arr = new int[]{3,9,-1,10,-2};

    // 优化 如果某趟排序中,没发生一次交换,可以提前结束排序
    boolean flag = true;
    for (int i = 0; i < arr.length-1; i++) {
        for (int j = 0; j < arr.length-i-1; j++) {
            if(arr[j] > arr[j+1]){
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;

                flag = false;
            }
        }

        if(flag){
            // 再一趟排序中,一次都没有发生交换
            break;
        }
    }

    System.out.println(Arrays.toString(arr));

}
选择排序(SelectSort)

时间复杂度O(n2)

在这里插入图片描述

/**
 * 选择排序
 */
public class SelectSort {

    public static void main(String[] args) {
        int[] arr = new int[]{3, 9, -1, 10, -2};

        selectSort(arr);
        System.out.println(Arrays.toString(arr));

    }

    // 选择排序
    public static void selectSort(int[] arr) {

        int max = 0;
        int maxIndex = 0;
        for (int i = 0; i < arr.length; i++) {
            max = arr[i];
            maxIndex = i;

            for (int j = i; j < arr.length - 1; j++) {
                if (arr[j] > max) {
                    max = arr[j];
                    maxIndex = j;
                }
            }
            if(maxIndex != i){
                arr[maxIndex] = arr[i];
                arr[i] = max;
            }
        }

    }
}
插入排序

在这里插入图片描述

代码实现

 public static void main(String[] args) {
        int[] arr = new int[]{3, 9, -1, 10, -2};
        insertSortMethod(arr);
        System.out.println(Arrays.toString(arr));

    }

    public static void insertSortMethod(int[] arr){
        int insertVal = 0;
        int insertIndex = 0;
        for (int i = 1; i < arr.length; i++) {
            // 定义待插入的数
            insertVal = arr[i];
            insertIndex = i -1;

            // 给insertVal 找到插入的位置
            // 说明
            // 1.insertIndex >= 0 保证在给insertVal 找到插入位置,不越界
            // 2.insertVal < arr[insertIndex] 待插入的数,还没有找到插入位置
            // 3.就需要将arr[insertIndex] 后移
            while(insertIndex >= 0 && insertVal < arr[insertIndex]){
                arr[insertIndex + 1] = arr[insertIndex];
                insertIndex--;
            }
            // 当退出while循环时,说明插入的位置找到了,insertIndex + 1
            // 这里我们判断是否需要赋值
            if(insertIndex + 1 != i){
                arr[insertIndex+1] = insertVal;
            }

        }
    }
基数排序

思路:
在这里插入图片描述
在这里插入图片描述

代码实现:

// 基数排序方法
public static void radixSort(int[] arr){

    // 取出最大值
    int max = arr[0];
    for (int i = 0; i < arr.length; i++) {
        if(arr[i] > max){
            max = arr[i];
        }
    }
    int maxLength = (max+"").length();
    int[][] bucket = new int[10][arr.length];
    int[] bucketElementCount = new int[10];

    for (int i = 0, n = 1; i < maxLength; i++,n*=10) {

        for (int j = 0; j < arr.length; j++) {
            // 取出每个元素的个位
            int digitOfElement = arr[j]/n %10;
            bucket[digitOfElement][bucketElementCount[digitOfElement]] = arr[j];
            bucketElementCount[digitOfElement]++;
        }
        // 按照这个桶的顺序
        int index = 0;

        for (int j = 0; j < bucketElementCount.length; j++) {
            if(bucketElementCount[j] != 0){
                for (int k = 0; k < bucketElementCount[j]; k++) {
                    arr[index++] = bucket[j][k];
                }
            }
            bucketElementCount[j] = 0;
        }
        System.out.println(Arrays.toString(arr));
    }

}

查找算法

二分查找法

前提要显示排好序的集合

二分查找的思路分析
1. 首先确定该数组的中间的下标
mid = (left + right) / 2
2. 然后让需要查找的数 findVal 和 arr[mid] 比较
2. 1 findVal > arr[mid] ,  说明你要查找的数在mid 的右边, 因此需要递归的向右查找
2.2 findVal < arr[mid], 说明你要查找的数在mid 的左边, 因此需要递归的向左查找
2.3  findVal == arr[mid] 说明找到,就返回

//什么时候我们需要结束递归.
1) 找到就结束递归 
2) 递归完整个数组,仍然没有找到findVal ,也需要结束递归  当 left > right 就需要退出

============================================================================
插值查找算法的 举例说明 

数组  arr = [1, 2, 3, ......., 100]

假如我们需要查找的值  1 

使用二分查找的话,我们需要多次递归,才能找到 1

使用插值查找算法
int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])

int mid = 0 + (99 - 0) * (1 - 1)/ (100 - 1) = 0 + 99 * 0 / 99 = 0 

比如我们查找的值 100

int mid = 0 + (99 - 0) * (100 - 1) / (100 - 1) = 0 + 99 * 99 / 99 = 0 + 99 = 99 


代码实现:

/**
 *  二分查找算法
 * @param arr 数组
 * @param left 左边索引
 * @param right 右边索引
 * @param findVal 要查找的值
 * @return 如果找到就返回下标,如果没有找到,就返回-1
 */
public static int binarySearch(int[] arr, int left, int right, int findVal){

    // 当left > right 时,说明递归整个数组,但是没有找到
    if(left > right){
        return -1;
    }

    int mid = (left + right) / 2;
    int midVal = arr[mid];

    if (findVal > midVal) {
        // 向右递归
        return binarySearch(arr, mid + 1, right, findVal);
    }else if( findVal < midVal){
        // 向左递归
        return binarySearch(arr, left, mid - 1, findVal);
    }else {
        return mid;
    }

}

问题

单链表的常见面试题有如下:

1)求单链表中有效节点的个数

2)查找单链表中的倒数第k个结点 【新浪面试题】

3)单链表的反转【腾讯面试题,有点难度】

4)从尾到头打印单链表 【百度,要求方式1:反向遍历 。 方式2:Stack栈】

5)合并两个有序的单链表,合并之后的链表依然有序【课后练习.】

栈实现综合计算器(中缀表达式)

在这里插入图片描述

思路:
在这里插入图片描述

迷宫回溯

// 使用递归回溯来给小球找路
// 说明
// 1.map 表示地图
// 2.i,j 表示从地图的哪个位置开始出发(1,1)
// 3.如果小球能到map[6][5] 位置,则说明通路找到。
// 4.约定: 当map[i][j] 为0表示该点没有走过 当为1表示墙;2 表示通路可以走;3表示该点已经走过,但是走不通
// 5.在走迷宫时,需要确认一个策略(方法)下->右->上->左
public static boolean setWay(int[][] map, int i, int j){
    if(map[6][5] == 2){
        // 通路已经找到
        return true;
    }else{
        if(map[i][j] == 0){
            // 如果当前这个点还没有走过
            // 按策略 下->右->上->左 走
            map[i][j] = 2;// 假定该点是可以走通
            if(setWay(map, i+1, j)){
                // 向下走
                return true;
            }if(setWay(map, i, j+1)){
                // 向右走
                return true;
            }if(setWay(map,i-1, j)){
                // 向上走
                return true;
            }if(setWay(map,i, j-1)){
                // 向上走
                return true;
            }else{
                // 说明该点走不通,是死路
                map[i][j] = 3;
                return false;
            }
        }else {
            // 如果map[i][j] != 0 ,可能是 1,2,3
            return false;
        }
    }
}
public static void main(String[] args) {

    // 先创建一个二维数组,模拟迷宫
    // 地图
    int[][] map = new int[8][7];
    // 使用1 表示墙
    // 上下全部置为1
    for (int i = 0; i < 7; i++) {
        map[0][i] = 1;
        map[7][i] = 1;
    }

    // 左右全部置为1
    for (int i = 0; i < 8; i++) {
        map[i][0] = 1;
        map[i][6] = 1;
    }

    //设置挡板, 1 表示
    map[3][1] = 1;
    map[3][2] = 1;
    // 输出地图
    System.out.println("地图的情况");
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 7; j++) {
            System.out.print(map[i][j] + " ");
        }
        System.out.println();
    }

    // 使用递归给小球找路
    setWay(map,1,1);

    // 输出新的地图,小球走过,并标识过的地图
    System.out.println("输出新的地图,小球走过,并标识过的地图");
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 7; j++) {
            System.out.print(map[i][j] + " ");
        }
        System.out.println();
    }

}

在这里插入图片描述

八皇后问题

在这里插入图片描述
在这里插入图片描述

代码实现

public class Queue8 {

    // 定义一个max表示共有多少个皇后
    int max = 8;
    // 定义数组array, 保存皇后放位置的结果,比如 arr = {0, 4, 5, 2, 6, 1, 3}
    int[] array = new int[max];
    static int count = 0;
    public static void main(String[] args) {

        Queue8 queue8 = new Queue8();
        queue8.check(0);
        System.out.println("一共有【"+count+"】解法");

    }

    // 编写一个方法,放置第n个皇后
    private  void check(int n){
        if(n == max) { // n = 8,其实8个皇后就已然放好
            print();
            return;
        }

        // 依次放入皇后,并判断是否冲突
        for (int i = 0; i < max; i++) {
            // 先把当前这个皇后 n , 放到改行的第1列
            array[n] = i;
            // 判断当放置第n个皇后到i列时,是否冲突
            if(judge(n)){ // 不冲突
                // 接着放n+1个皇后,既开始递归
                check(n + 1);
            }
            // 如果冲突,就继续执行array[n] = i; 既将第n个皇后,放置本行的后移一个位置
        }
    }

    // 查看当我们放置第n个皇后,就去检查该皇后是否和前面已经摆放的皇后冲突
    private boolean judge(int n){
        for (int i = 0; i < n; i++) {
            // 说明
            // 1.array[i] == array[n] 表示判断第n个皇后是否和前面的n-1个皇后在同一列
            // 2.Math.abs(n-1) == Math.abs(array[n]-array[i]) 表示判断第n个皇后是否和第i个皇后在同一斜线
            // 3.判断是否在同一行,没有必要, n每次都在递增
            if(array[i] == array[n] || Math.abs(n-i) == Math.abs(array[n] - array[i]) ){
                return false;
            }
        }
        return true;
    }
    // 写一个方法,可以将皇后摆放的位置输出
    private void print(){
        count++;
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值