• 数据结构和算法——数据结构


    目录

    线性结构

     队列结构的队列

    链表结构的队列

    链表的面试题

    单向链表应用场景

    约瑟夫环问题

    栈结构

    中缀表达式

    前缀表达式

    后缀表达式

    非线性结构

    递归解决迷宫问题

    递归解决八皇后问题


    线性结构

    顺序存储方式,顺序表

    常见的顺序存储结构有:数组、队列、链表、栈

    链式存储方式,链表

    数组结构

    队列结构的队列

    队列可以使用数组结构或者链表结构来存储,先入先出,后进后出。

    数组结构的队列:

    1. public class Demo {
    2. public static void main(String[] args) {
    3. CircleArrayQueue arrayQueue = new CircleArrayQueue(3);
    4. char key;
    5. Scanner scanner = new Scanner(System.in);
    6. boolean loop = true;
    7. while (loop) {
    8. System.out.println("s(show):显示队列");
    9. System.out.println("e(exit):退出程序");
    10. System.out.println("a(add):添加数据到队列");
    11. System.out.println("g(get):从队列取出数据");
    12. System.out.println("h(head):查看队列头的数据");
    13. key = scanner.next().charAt(0);
    14. switch (key) {
    15. case 's':
    16. arrayQueue.showQueue();
    17. break;
    18. case 'a':
    19. System.out.println("请输入一个数字");
    20. int value = scanner.nextInt();
    21. arrayQueue.addQueue(value);
    22. break;
    23. case 'g':
    24. try {
    25. int res = arrayQueue.getQueue();
    26. System.out.println("取出的数据为=" + res);
    27. } catch (Exception e) {
    28. System.out.println(e.getMessage());
    29. }
    30. break;
    31. case 'e':
    32. loop = false;
    33. scanner.close();
    34. System.out.println("程序退出...");
    35. break;
    36. case 'h':
    37. try {
    38. int res = arrayQueue.headQueue();
    39. System.out.println("查看的数据为=" + res);
    40. } catch (Exception e) {
    41. System.out.println(e.getMessage());
    42. }
    43. break;
    44. default:
    45. break;
    46. }
    47. }
    48. }
    49. }
    50. class CircleArrayQueue {
    51. private int maxSize;
    52. // 指向队列头的位置
    53. private int front;
    54. // 指向队列尾的数据的下一个的位置,它指向的队尾的数据代表有值的
    55. private int rear;
    56. private int[] arr;
    57. public CircleArrayQueue(int arrMaxSize) {
    58. // 实际上队列有maxSize个元素,因为空出了一个位置
    59. maxSize = arrMaxSize + 1;
    60. arr = new int[maxSize];
    61. front = rear = 0;
    62. }
    63. public boolean isFull() {
    64. return (rear + 1) % maxSize == front;
    65. }
    66. public boolean isEmpty() {
    67. return front == rear;
    68. }
    69. public void addQueue(int n) {
    70. if (isFull()) {
    71. System.out.println("队列为满,不能加入数据");
    72. return;
    73. }
    74. arr[rear] = n;
    75. rear++;
    76. if (rear % maxSize == 0) {
    77. rear = 0;
    78. }
    79. }
    80. public int getQueue() {
    81. if (isEmpty()) {
    82. throw new RuntimeException("队列为空,不能取值");
    83. }
    84. int res = arr[front];
    85. front++;
    86. if (front % maxSize == 0) {
    87. front = 0;
    88. }
    89. return res;
    90. }
    91. public void showQueue() {
    92. if (isEmpty()) {
    93. System.out.println("队列为空,没有数据");
    94. return;
    95. }
    96. // for (int i = front; i != rear; i = (i + 1) % maxSize) {
    97. for (int i = front; i < front + size(); i++) {
    98. System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
    99. }
    100. }
    101. public int headQueue() {
    102. if (isEmpty()) {
    103. throw new RuntimeException("队列为空,没有头数据");
    104. }
    105. return arr[front];
    106. }
    107. private int size() {
    108. return (rear + maxSize - front) % maxSize;
    109. }
    110. }

     栈结构

    1. public class ArrayStackDemo {
    2. public static void main(String[] args) {
    3. ArrayStack stack = new ArrayStack(4);
    4. String key;
    5. boolean loop = true;
    6. Scanner scanner = new Scanner(System.in);
    7. while (loop) {
    8. System.out.println("show:表示显示栈");
    9. System.out.println("exit:表示退出栈");
    10. System.out.println("push:表示压栈");
    11. System.out.println("pop:表示出栈");
    12. System.out.println("请输入你的选择:");
    13. key = scanner.next();
    14. switch (key) {
    15. case "s":
    16. stack.list();
    17. break;
    18. case "e":
    19. loop = false;
    20. break;
    21. case "pu":
    22. try {
    23. System.out.println("请输入要压栈的数据");
    24. int value = scanner.nextInt();
    25. stack.push(value);
    26. } catch (Exception e) {
    27. System.out.println(e.getMessage());
    28. }
    29. break;
    30. case "po":
    31. try {
    32. System.out.println(stack.pop());
    33. } catch (Exception e) {
    34. System.out.println(e.getMessage());
    35. }
    36. break;
    37. default:
    38. System.out.println("输入有误");
    39. break;
    40. }
    41. }
    42. System.out.println("程序退出了...");
    43. }
    44. }
    45. class ArrayStack {
    46. private int maxSize;
    47. private int[] stack;
    48. private int top = -1;
    49. public ArrayStack(int maxSize) {
    50. this.maxSize = maxSize;
    51. stack = new int[maxSize];
    52. }
    53. public boolean isFull() {
    54. return top == maxSize - 1;
    55. }
    56. public boolean isEmpty() {
    57. return top == -1;
    58. }
    59. public void push(int value) {
    60. if (isFull()) {
    61. System.out.println("栈满");
    62. return;
    63. }
    64. top++;
    65. stack[top] = value;
    66. }
    67. public int pop() {
    68. if (isEmpty()) {
    69. throw new RuntimeException("栈空,没有数据");
    70. }
    71. int res = stack[top];
    72. top--;
    73. return res;
    74. }
    75. public void list() {
    76. if (isEmpty()) {
    77. System.out.println("栈空,没有数据");
    78. return;
    79. }
    80. for (int i = top; i >= 0; i--) {
    81. System.out.printf("a[%d]=%d\n", i, stack[i]);
    82. }
    83. }
    84. }
    中缀表达式

    人阅读的表达式。用来实现一个简单的计算器:

    1. public class Calculator {
    2. public static void main(String[] args) {
    3. String expression = "7*2*2-5+1-5+3-4";
    4. ArrayStack2 numStack = new ArrayStack2(10);
    5. ArrayStack2 operStack = new ArrayStack2(10);
    6. int index = 0;
    7. int num1 = 0;
    8. int num2 = 0;
    9. int oper = 0;
    10. int res = 0;
    11. char ch = ' ';
    12. while (true) {
    13. ch = expression.substring(index, index + 1).charAt(0);
    14. if (operStack.isOper(ch)) {
    15. if (!operStack.isEmpty()) {
    16. if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
    17. num1 = numStack.pop();
    18. num2 = numStack.pop();
    19. oper = operStack.pop();
    20. res = numStack.cal(num1, num2, (char) oper);
    21. numStack.push(res);
    22. operStack.push(ch);
    23. } else {
    24. operStack.push(ch);
    25. }
    26. } else {
    27. operStack.push(ch);
    28. }
    29. } else {
    30. // numStack.push(ch - '0');
    31. int keepNum = ch - '0';
    32. while (index < expression.length() - 1) {
    33. index++;
    34. ch = expression.substring(index, index + 1).charAt(0);
    35. if (!operStack.isOper(ch)) {
    36. keepNum = keepNum * 10 + (ch - '0');
    37. } else {
    38. index--;
    39. break;
    40. }
    41. }
    42. numStack.push(keepNum);
    43. }
    44. index++;
    45. if (index == expression.length()) {
    46. break;
    47. }
    48. }
    49. while (true) {
    50. if (operStack.isEmpty()) {
    51. break;
    52. }
    53. num1 = numStack.pop();
    54. num2 = numStack.pop();
    55. oper = operStack.pop();
    56. res = numStack.cal(num1, num2, (char) oper);
    57. numStack.push(res);
    58. }
    59. System.out.printf("表达式 %s = %d\n", expression, numStack.pop());
    60. }
    61. }
    62. class ArrayStack2 {
    63. private int maxSize;
    64. private int[] stack;
    65. private int top = -1;
    66. public ArrayStack2(int maxSize) {
    67. this.maxSize = maxSize;
    68. stack = new int[maxSize];
    69. }
    70. public boolean isFull() {
    71. return top == maxSize - 1;
    72. }
    73. public boolean isEmpty() {
    74. return top == -1;
    75. }
    76. public void push(int value) {
    77. if (isFull()) {
    78. System.out.println("栈满");
    79. return;
    80. }
    81. top++;
    82. stack[top] = value;
    83. }
    84. public int pop() {
    85. if (isEmpty()) {
    86. throw new RuntimeException("栈空,没有数据");
    87. }
    88. int res = stack[top];
    89. top--;
    90. return res;
    91. }
    92. public void list() {
    93. if (isEmpty()) {
    94. System.out.println("栈空,没有数据");
    95. return;
    96. }
    97. for (int i = top; i >= 0; i--) {
    98. System.out.printf("a[%d]=%d\n", i, stack[i]);
    99. }
    100. }
    101. public int priority(int oper) {
    102. if (oper == '*' || oper == '/') {
    103. return 1;
    104. } else if (oper == '+' || oper == '-') {
    105. return 0;
    106. }
    107. return -1;
    108. }
    109. public boolean isOper(char val) {
    110. return val == '+' || val == '-' || val == '*' || val == '/';
    111. }
    112. public int cal(int num1, int num2, char oper) {
    113. int res = 0;
    114. switch (oper) {
    115. case '+':
    116. res = num1 + num2;
    117. break;
    118. case '-':
    119. res = num2 - num1;
    120. break;
    121. case '*':
    122. res = num1 * num2;
    123. break;
    124. case '/':
    125. res = num2 / num1;
    126. break;
    127. default:
    128. break;
    129. }
    130. return res;
    131. }
    132. public int peek() {
    133. return stack[top];
    134. }
    135. }
    前缀表达式

    也叫波兰表达式,(3+4)x5-6对应的前缀表达式为 - x + 3 4 5 6,从右向左扫描,遇到数字的时,将数字压入,遇到运算符时,弹出栈顶的两个数字进行计算,将结果压入栈,

    后缀表达式

    也叫逆波兰表达式,(3+4)x5-6 对应的逆波兰表达式为 3 4 + 5 x 6 - ,从左到右扫描,遇到数字把数字压栈,遇到运算符弹出栈顶的两个数字,进行运算,最后将结果压栈。可以用来写计算器:

    代码:

    1. public class PolandNotation {
    2. public static void main(String[] args) {
    3. // 逆波兰表达式
    4. // (3+4)*5-6
    5. // String suffixExpression = "3 4 + 5 * 6 -";
    6. // 4*5-8+60+8/2
    7. String suffixExpression = "4 5 * 8 - 60 + 8 2 / +";
    8. List list = getListString(suffixExpression);
    9. int res = calculate(list);
    10. }
    11. public static List getListString(String suffixExpression) {
    12. String[] s = suffixExpression.split(" ");
    13. List list = new ArrayList<>();
    14. for (String ele : s) {
    15. list.add(ele);
    16. }
    17. return list;
    18. }
    19. public static int calculate(List list) {
    20. Stack stack = new Stack<>();
    21. for (String item : list) {
    22. if (item.matches("\\d+")) {
    23. stack.push(item);
    24. } else {
    25. int n2 = Integer.parseInt(stack.pop());
    26. int n1 = Integer.parseInt(stack.pop());
    27. int res = 0;
    28. if (item.equals("+")) {
    29. res = n1 + n2;
    30. } else if (item.equals("-")) {
    31. res = n1 - n2;
    32. } else if (item.equals("*")) {
    33. res = n1 * n2;
    34. } else if (item.equals("/")) {
    35. res = n1 / n2;
    36. } else {
    37. throw new RuntimeException("运算符有误");
    38. }
    39. stack.push(res + "");
    40. }
    41. }
    42. return Integer.parseInt(stack.pop());
    43. }
    44. }

    如何中缀转后缀表达式:

    1)初始化两个栈,运算符栈s1和存储中间结果的栈s2;

    2)从左到右扫描中缀表达式;

    3)遇到数时,压入栈s2;

    4)遇到运算符时,比较其与栈s1栈顶的优先级:

    1.如果栈s1为空,或栈顶运算符为左括号,则直接将此运算符压栈s1;

    2.否则,若优先级比栈顶的高,也将运算符压入栈s1;

    3.否则,将栈s1栈顶的运算符弹出并压入栈s2,再次(4 - 1)与 s1 中新的栈顶运算符比较;

    5)遇到括号时:

    1.如果是左括号,则直接压入栈s1;

    2.如果是右括号,则依次弹出s1栈顶的运算符,并压入栈s2,直到遇到左括号为止,此时将一对括号丢弃;

    6)重复步骤2至5,直到表达式最右边;

    7)将s1中剩余的运算符依次弹出并压入栈s2;

    8)依次弹出栈s2中的元素并输出,结果逆序即为中缀表达式对应的后缀表达式。

    代码:

    1. public class PolandNotation {
    2. public static void main(String[] args) {
    3. String expression = "1+((2+3)*4)-5"; // 后缀表达式:1 2 3 + 4 * + 5 -
    4. List list = infixExpressionList(expression);
    5. List result = parseSuffixExpreesionList(list);
    6. }
    7. public static List parseSuffixExpreesionList(List list) {
    8. Stack s1 = new Stack<>(); // 运算符栈
    9. List s2 = new ArrayList<>(); // 存储中间结果的栈
    10. for (String item : list) {
    11. if (item.matches("\\d+")) {
    12. s2.add(item);
    13. } else if (item.equals("(")) {
    14. s1.push(item);
    15. } else if (item.equals(")")) {
    16. while (!s1.peek().equals("(")) {
    17. s2.add(s1.pop());
    18. }
    19. s1.pop(); // 弹栈 (
    20. } else {
    21. while (!s1.isEmpty() && Operation.getValue(s1.peek()) >= Operation.getValue(item)) {
    22. s2.add(s1.pop());
    23. }
    24. s1.add(item);
    25. }
    26. }
    27. while (!s1.isEmpty()) {
    28. s2.add(s1.pop());
    29. }
    30. return s2;
    31. }
    32. private static List infixExpressionList(String s) {
    33. ArrayList list = new ArrayList<>();
    34. int i = 0;
    35. String str;
    36. char c;
    37. do {
    38. c = s.charAt(i);
    39. if (c < '0' || c > '9') {
    40. list.add("" + c);
    41. i++;
    42. } else {
    43. str = "";
    44. while (i < s.length() && (c = s.charAt(i)) >= '0' && c <= '9') {
    45. str += c;
    46. i++;
    47. }
    48. list.add(str);
    49. }
    50. } while (i < s.length());
    51. return list;
    52. }
    53. }
    54. class Operation {
    55. private static int ADD = 1;
    56. private static int SUB = 1;
    57. private static int MUL = 1;
    58. private static int DIV = 1;
    59. public static int getValue(String operation) {
    60. int result = 0;
    61. switch (operation) {
    62. case "+":
    63. result = ADD;
    64. break;
    65. case "-":
    66. result = SUB;
    67. break;
    68. case "*":
    69. result = MUL;
    70. break;
    71. case "/":
    72. result = DIV;
    73. break;
    74. default:
    75. System.out.println("不存在该运算符");
    76. break;
    77. }
    78. return result;
    79. }
    80. }

    链表结构的队列

    1. public class SingleLinkListDemo {
    2. public static void main(String[] args) {
    3. HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
    4. HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
    5. HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
    6. SingleLinkList singleLinkList = new SingleLinkList();
    7. singleLinkList.add(hero3);
    8. singleLinkList.add(hero2);
    9. singleLinkList.add(hero1);
    10. // singleLinkList.add(hero3);
    11. // HeroNode newHero = new HeroNode(3, "张三", "法外狂徒");
    12. // singleLinkList.update(newHero);
    13. HeroNode delHero1 = new HeroNode(1, "", "");
    14. singleLinkList.del(delHero1);
    15. singleLinkList.reverse();
    16. singleLinkList.list();
    17. }
    18. }
    19. class SingleLinkList {
    20. private HeroNode headNode = new HeroNode(0, "", "");
    21. // 非递归反转
    22. public void reverse3() {
    23. if (headNode.getNext() == null || headNode.getNext().getNext() == null) {
    24. return;
    25. }
    26. HeroNode nextNode1, nextNode2, nextNode3;
    27. nextNode1 = headNode.getNext();
    28. nextNode2 = nextNode1.getNext();
    29. nextNode3 = nextNode2.getNext();
    30. nextNode2.setNext(nextNode1);
    31. nextNode1.setNext(null);
    32. while (nextNode3 != null) {
    33. nextNode1 = nextNode2;
    34. nextNode2 = nextNode3;
    35. nextNode3 = nextNode3.getNext();
    36. nextNode2.setNext(nextNode1);
    37. }
    38. headNode.setNext(nextNode2);
    39. }
    40. // 递归反转
    41. public void reverse() {
    42. HeroNode nextNode = headNode.getNext();
    43. headNode.setNext(reverse2(headNode.getNext()));
    44. nextNode.setNext(null);
    45. }
    46. private HeroNode reverse2(HeroNode heroNode) {
    47. if (heroNode.getNext() != null) {
    48. HeroNode lastNode = reverse2(heroNode.getNext());
    49. heroNode.getNext().setNext(heroNode);
    50. return lastNode;
    51. }
    52. return heroNode;
    53. }
    54. public void del(HeroNode delHeroNode) {
    55. if (headNode.getNext() == null) {
    56. System.out.println("链表为空");
    57. return;
    58. }
    59. HeroNode preNode, nextNode;
    60. preNode = headNode;
    61. nextNode = headNode.getNext();
    62. while (nextNode != null) {
    63. if (nextNode.getNo() == delHeroNode.getNo()) {
    64. preNode.setNext(nextNode.getNext());
    65. // nextNode.setNext(null);
    66. return;
    67. }
    68. preNode = nextNode;
    69. nextNode = nextNode.getNext();
    70. }
    71. System.out.println("删除编号= " + delHeroNode.getNo() + " 的元素没有找到");
    72. }
    73. public void update(HeroNode newHeroNode) {
    74. if (headNode.getNext() == null) {
    75. System.out.println("链表为空");
    76. return;
    77. }
    78. HeroNode preNode, nextNode;
    79. preNode = headNode;
    80. nextNode = headNode.getNext();
    81. while (nextNode != null) {
    82. if (nextNode.getNo() == newHeroNode.getNo()) {
    83. newHeroNode.setNext(nextNode.getNext());
    84. preNode.setNext(newHeroNode);
    85. return;
    86. }
    87. preNode = nextNode;
    88. nextNode = nextNode.getNext();
    89. }
    90. System.out.println("编号= " + newHeroNode.getNo() + " 的元素没有找到");
    91. }
    92. public void add(HeroNode heroNode) {
    93. HeroNode nextNode, preNode;
    94. preNode = headNode;
    95. nextNode = headNode.getNext();
    96. // 头插法
    97. if (nextNode == null) {
    98. headNode.setNext(heroNode);
    99. heroNode.setNext(null);
    100. return;
    101. }
    102. // 中插法
    103. while (nextNode != null) {
    104. if (heroNode.getNo() < nextNode.getNo()) {
    105. preNode.setNext(heroNode);
    106. heroNode.setNext(nextNode);
    107. return;
    108. }
    109. // 相同的数据不能进行插入
    110. if (heroNode.getNo() == nextNode.getNo()) {
    111. System.out.println("编号=" + heroNode.getNo() + " 已存在,不能添加");
    112. return;
    113. }
    114. preNode = nextNode;
    115. nextNode = nextNode.getNext();
    116. }
    117. // 尾插法
    118. preNode.setNext(heroNode);
    119. heroNode.setNext(null);
    120. }
    121. public void list() {
    122. HeroNode tmpNode = headNode.getNext();
    123. if (tmpNode == null) {
    124. System.out.println("链表为空");
    125. return;
    126. }
    127. while (tmpNode != null) {
    128. System.out.println("node= " + tmpNode + " -->");
    129. tmpNode = tmpNode.getNext();
    130. }
    131. }
    132. }
    133. @Data
    134. class HeroNode {
    135. private int no;
    136. private String name;
    137. private String nickName;
    138. private HeroNode next;
    139. public HeroNode(int hNo, String hName, String hNickName) {
    140. this.no = hNo;
    141. this.name = hName;
    142. this.nickName = hNickName;
    143. }
    144. @Override
    145. public String toString() {
    146. return "HeroNode{" +
    147. "no=" + no +
    148. ", name='" + name + '\'' +
    149. ", nickName='" + nickName + '\'' +
    150. '}';
    151. }
    152. }

    约瑟夫环问题

    1. public class Josephu {
    2. public static void main(String[] args) {
    3. CircleSingleLinkedList list = new CircleSingleLinkedList();
    4. list.addBoy(5);
    5. list.countBoy(1, 2, 5);
    6. // list.showBoy();
    7. }
    8. }
    9. class CircleSingleLinkedList {
    10. private Boy first = null;
    11. public void addBoy(int nums) {
    12. if (nums < 2) {
    13. System.out.println("nums的值不正确");
    14. return;
    15. }
    16. Boy curBoy = null;
    17. for (int i = 0; i < nums; i++) {
    18. Boy boy = new Boy(i + 1);
    19. if (i == 0) {
    20. first = boy;
    21. first.setNext(first);
    22. curBoy = first;
    23. } else {
    24. curBoy.setNext(boy);
    25. boy.setNext(first);
    26. curBoy = boy;
    27. }
    28. }
    29. }
    30. public void showBoy() {
    31. if (first == null) {
    32. System.out.println("链表为空");
    33. return;
    34. }
    35. Boy curBoy = first;
    36. do {
    37. System.out.println("编号= " + curBoy.getNo() + " -->");
    38. curBoy = curBoy.getNext();
    39. } while (curBoy != first);
    40. }
    41. /**
    42. * @param startNo 从第几个开始
    43. * @param countNum 数几下
    44. * @param nums 最初有多少个小孩
    45. */
    46. public void countBoy(int startNo, int countNum, int nums) {
    47. if (first == null || startNo < 1 || startNo > nums) {
    48. System.out.println("参数输入有误,请重新输入");
    49. return;
    50. }
    51. Boy helper = first;
    52. while (helper.getNext() != first) {
    53. helper = helper.getNext();
    54. }
    55. for (int i = 0; i < startNo - 1; i++) {
    56. first = first.getNext();
    57. helper = helper.getNext();
    58. }
    59. while (helper != first) {
    60. for (int i = 0; i < countNum - 1; i++) {
    61. first = first.getNext();
    62. helper = helper.getNext();
    63. }
    64. System.out.println("小孩 " + first.getNo() + " 出圈");
    65. first = first.getNext();
    66. helper.setNext(first);
    67. // nums--;
    68. }
    69. System.out.println("最后留在圈中的小孩编号 " + first.getNo());
    70. }
    71. }
    72. class Boy {
    73. private int no;
    74. private Boy next;
    75. public Boy(int no) {
    76. this.no = no;
    77. }
    78. //#region get|set
    79. public int getNo() {
    80. return no;
    81. }
    82. public void setNo(int no) {
    83. this.no = no;
    84. }
    85. public Boy getNext() {
    86. return next;
    87. }
    88. public void setNext(Boy next) {
    89. this.next = next;
    90. }
    91. //#endregion
    92. }

    非线性结构

    常见的非线性结构有:二维数组、多维数组、广义表、树结构、图结构。

    图结构

    递归解决迷宫问题

    1. public class MiGong {
    2. public static void main(String[] args) {
    3. int[][] map = new int[8][7]; // 1 墙 0 未走 2 已走
    4. for (int i = 0; i < 7; i++) {
    5. map[0][i] = 1;
    6. map[7][i] = 1;
    7. map[i][0] = 1;
    8. map[i][6] = 1;
    9. }
    10. map[3][1] = 1;
    11. map[3][2] = 1;
    12. setWay(map, 1, 1);
    13. }
    14. public static boolean setWay(int[][] map, int i, int j) {
    15. if (map[6][5] == 2) {
    16. return true;
    17. } else {
    18. if (map[i][j] == 0) {
    19. map[i][j] = 2;
    20. if (setWay(map, i + 1, j)) { // 上
    21. return true;
    22. } else if (setWay(map, i, j + 1)) { // 又
    23. return true;
    24. } else if (setWay(map, i - 1, j)) { // 下
    25. return true;
    26. } else if (setWay(map, i, j - 1)) { // 左
    27. return true;
    28. } else {
    29. map[i][j] = 3; // 已走未通过
    30. return false;
    31. }
    32. } else {
    33. return false; // 值可能是 1、2、3
    34. }
    35. }
    36. }
    37. }

    递归解决八皇后问题

    1. public class Queue8 {
    2. int max = 8;
    3. int[] array = new int[max];
    4. /**
    5. * 有几种解法
    6. **/
    7. int count = 0;
    8. // int judgeCount=0;
    9. public static void main(String[] args) {
    10. Queue8 queue8 = new Queue8();
    11. queue8.check(0);
    12. // System.out.println("解法count=" + queue8.count + "种");
    13. }
    14. /**
    15. * 放置第n个皇后
    16. *
    17. * @param n
    18. */
    19. private void check(int n) {
    20. if (n == max) {
    21. print();
    22. return;
    23. }
    24. for (int i = 0; i < max; i++) {
    25. array[n] = i;
    26. if (judge(n)) { // 不冲突
    27. check(n + 1);
    28. }
    29. }
    30. }
    31. /**
    32. * 是否与之前的皇后冲突
    33. *
    34. * @param n 第n个皇后,从0开始
    35. * @return
    36. */
    37. private boolean judge(int n) {
    38. // judgeCount++;
    39. for (int i = 0; i < n; i++) {
    40. if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[i] - array[n])) { // 同列 同斜线
    41. return false;
    42. }
    43. }
    44. return true;
    45. }
    46. private void print() {
    47. for (int i = 0; i < array.length; i++) {
    48. System.out.print(array[i] + " ");
    49. }
    50. System.out.println();
    51. count++;
    52. }
    53. }

    树结构

    数据结构和算法——树结构-CSDN博客

    增强的顺序结构

    哈希表

    是数组加链表的数据结构,用到了拉链法。

    实例问题:

    有一个公司,当有新员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址...),当输入该员工的id时,要求查找到该员工的所有信息。

    1. public class HashTableDemo {
    2. public static void main(String[] args) {
    3. HashTable hashTable = new HashTable(7);
    4. String key = "";
    5. Scanner scanner = new Scanner(System.in);
    6. boolean loop = true;
    7. while (loop) {
    8. System.out.println("add:添加雇员");
    9. System.out.println("list:显示雇员");
    10. System.out.println("find:查找雇员");
    11. System.out.println("del:删除雇员");
    12. System.out.println("exit:退出系统");
    13. key = scanner.nextLine();
    14. switch (key) {
    15. case "a":
    16. System.out.println("输入id:");
    17. int id = scanner.nextInt();
    18. System.out.println("输入名字:");
    19. String name = scanner.next();
    20. Emp emp = new Emp(id, name);
    21. hashTable.add(emp);
    22. continue;
    23. case "l":
    24. hashTable.list();
    25. break;
    26. case "d":
    27. System.out.println("输入id:");
    28. id = scanner.nextInt();
    29. hashTable.delEmpById(id);
    30. break;
    31. case "f":
    32. System.out.println("输入id:");
    33. id = scanner.nextInt();
    34. emp = hashTable.findEmpById(id);
    35. if (emp == null) {
    36. System.out.println("该雇员不存在");
    37. } else {
    38. System.out.println(emp);
    39. }
    40. break;
    41. case "e":
    42. loop = false;
    43. break;
    44. default:
    45. loop = true;
    46. break;
    47. }
    48. }
    49. }
    50. }
    51. class Emp {
    52. public int id;
    53. public String name;
    54. public Emp next;
    55. public Emp(int id, String name) {
    56. this.id = id;
    57. this.name = name;
    58. this.next = next;
    59. }
    60. @Override
    61. public String toString() {
    62. return "Emp{" +
    63. "id=" + id +
    64. ", name='" + name + '\'' +
    65. '}';
    66. }
    67. }
    68. class EmpLinkedList {
    69. private Emp head;
    70. public EmpLinkedList(Emp head) {
    71. this.head = head;
    72. }
    73. public void add(Emp emp) {
    74. if (head == null) {
    75. head = emp;
    76. } else {
    77. Emp curEmp = head;
    78. while (curEmp.next != null) {
    79. curEmp = curEmp.next;
    80. }
    81. curEmp.next = emp;
    82. }
    83. }
    84. public void list() {
    85. if (head == null) {
    86. System.out.println("当前链表为空");
    87. return;
    88. }
    89. System.out.println("当前链表的信息为:");
    90. Emp curEmp = head;
    91. while (curEmp != null) {
    92. System.out.println("emp= " + curEmp);
    93. curEmp = curEmp.next;
    94. }
    95. }
    96. public Emp findEmpById(int id) {
    97. Emp curEmp = head;
    98. while (curEmp != null) {
    99. if (curEmp.id == id) {
    100. return curEmp;
    101. }
    102. curEmp = curEmp.next;
    103. }
    104. return null;
    105. }
    106. public void delEmpById(int id) {
    107. if (head == null) {
    108. System.out.println("该雇员不存在");
    109. return;
    110. }
    111. if (head.id == id) {
    112. head = null;
    113. return;
    114. }
    115. Emp curEmp = head;
    116. while (curEmp.next != null) {
    117. if (curEmp.next.id == id) {
    118. curEmp.next = curEmp.next.next;
    119. System.out.println("删除雇员成功");
    120. return;
    121. }
    122. curEmp = curEmp.next;
    123. }
    124. System.out.println("该雇员不存在");
    125. }
    126. }
    127. class HashTable {
    128. private EmpLinkedList[] empListedListArray;
    129. private int size;
    130. public HashTable(int size) {
    131. this.size = size;
    132. this.empListedListArray = new EmpLinkedList[this.size];
    133. }
    134. public void add(Emp emp) {
    135. // 根据id得到下标
    136. int index = hashFun(emp.id);
    137. if (empListedListArray[index] == null) {
    138. EmpLinkedList empLinkedList = new EmpLinkedList(emp);
    139. empListedListArray[index] = empLinkedList;
    140. } else {
    141. empListedListArray[index].add(emp);
    142. }
    143. }
    144. public int hashFun(int id) {
    145. return id % this.size;
    146. }
    147. public void list() {
    148. for (int i = 0; i < this.size; i++) {
    149. EmpLinkedList empLinkedList = empListedListArray[i];
    150. if (empLinkedList != null) {
    151. empLinkedList.list();
    152. System.out.println("----------------");
    153. }
    154. }
    155. }
    156. public Emp findEmpById(int id) {
    157. int index = hashFun(id);
    158. if (empListedListArray[index] == null) {
    159. return null;
    160. }
    161. Emp emp = empListedListArray[index].findEmpById(id);
    162. return emp;
    163. }
    164. public void delEmpById(int id) {
    165. int index = hashFun(id);
    166. if (empListedListArray[index] == null) {
    167. System.out.println("该雇员不存在");
    168. return;
    169. }
    170. empListedListArray[index].delEmpById(id);
    171. }
    172. }

    数组加二叉树的结构。

    参考教程视频:【尚硅谷】数据结构与算法(Java数据结构与算法)_哔哩哔哩_bilibili

  • 相关阅读:
    修改ubuntu终端目录背景颜色
    【笔试强训选择题】Day35.习题(错题)解析
    FDTD script command (对结构/数据操作)
    Dreamweaver网页作业——紫罗兰永恒花园动漫价绍网页 7页,含有table表格,js表单验证还有首页视频。以及列表页。浮动布局。div+css+js
    [YOLOv7]基于YOLO&Deepsort的车速&车流量检测系统(源码&部署教程)
    [Kubernetes] 多调度器(1/3):如何编译scheduler,以默认调度器 kube-scheduler为例
    k8s二进制(ETCD的部署安装)
    Android 11 AudioPolicyService 启动流程
    【Flink源码】再谈Flink程序提交流程(下)
    浏览器插件不会装?保姆级教程分享!
  • 原文地址:https://blog.csdn.net/m0_58961367/article/details/133584081