【记录数据结构复习day2(java)】

普通表达式的计算


public class ArrayStackDemo {
    public static void main(String[] args) {
        String expr = "3-2-1";
//        String expr = "96+54*2-34-64+87+65-34*2-57";
        ArrStack numStack = new ArrStack(20);
        ArrStack opeStack = new ArrStack(20);
        //扫描表达式
        int index = 0;
        //定义一个str记录扫描到的多位数
        StringBuffer str = new StringBuffer();
        char ch = ' '; // 记录扫描到的字符
        while(index < expr.length()) {
            str.replace(0, str.length(), "");
            ch = expr.substring(index, index + 1).charAt(0);
            // 如果ch是一个数,那么要判断下一位是数还是符号
            if(!numStack.isOperator(ch)) {
                while(!numStack.isOperator(ch) && index < expr.length()) {
                    index ++;
                    str.append(ch);
                    if(index < expr.length()) ch = expr.substring(index, index + 1).charAt(0);
                }
                numStack.push(Integer.parseInt(str.toString()));
            }
            else { // 是一个符号
                //当前扫描到的符号的优先级大于原来的优先级或者符号栈为空,那么直接入栈
                if(opeStack.isEmpty() || opeStack.priority(opeStack.peek()) < opeStack.priority(ch))
                    opeStack.push(ch);
                else { // 当前扫描到的符号优先级小于等于符号栈顶的优先级
                    int num2 = numStack.pop();
                    int num1 = numStack.pop();
                    numStack.push(numStack.calculate(num1, num2, (char)opeStack.pop()));
                    //如果符号栈顶端的符号是 '-' 那么还要先计算其中的减号
                    if(!opeStack.isEmpty() && opeStack.peek() == '-') {
                        //先从数栈中pop出两个数
                        num2 = numStack.pop();
                        num1 = numStack.pop();
                        numStack.push(numStack.calculate(num1, num2, (char)opeStack.pop()));
                    }
                    opeStack.push(ch);
                }
                index ++;
            }
        }
        //扫描结束
        while(!opeStack.isEmpty()){
            int num2 = numStack.pop();
            int num1 = numStack.pop();
            numStack.push(numStack.calculate(num1, num2, (char)opeStack.pop()));
        }
        System.out.printf("表达式%s = %d\n", expr, numStack.pop());
    }
}
class ArrStack {
    private int[] arr;
    private int maxSize;
    private int rear;
    public ArrStack(int maxSize) {
        this.maxSize = maxSize;
        arr = new int[maxSize];
        rear = -1;
    }
    public boolean isEmpty() {
        return rear == -1;
    }
    public boolean isFull() {
        return rear == maxSize - 1;
    }
    public void push(int ele) {
        if(isFull()) {
            System.out.println("栈已满,无法加入新元素~~");
            return;
        }
        arr[++ rear] = ele;
    }
    public int pop() {
        if(isEmpty())
            throw new RuntimeException("栈为空,无法pop出元素~~");
        return arr[rear --];
    }
    public int peek() {
        if(isEmpty())
            throw new RuntimeException("栈为空,无法peek~~");
        return arr[rear];
    }
    public void showData() {
        if(isEmpty()) {
            System.out.println("栈为空,没有元素可show~~");
            return;
        }
        for (int i = 0; i <= rear; i++) {
            System.out.printf("arr[%d] = %d\t", i, arr[i]);
        }
        System.out.println();
    }
    public boolean isOperator(char ch) {
        return ch == '+' || ch == '-' || ch == '*' || ch == '/';
    }
    public int priority(int ope) {
        return (ope == '*' || ope == '/')? 1: 0;
    }
    public int calculate(int num1, int num2, char ope) {
        switch (ope) {
            case'+':
                return num1 + num2;
            case'-':
                return num1 - num2;
            case'*':
                return num1 * num2;
            case'/':
                return num1 / num2;
            default:
                throw new RuntimeException("操作符错误~~请检查");
        }
    }
}

普通中缀表达式转逆波兰表达式后再计算

public class PolandNotation {
    /**
     * 1. 初始化两个栈,运算符栈s1和中间栈s2
     * 2. 从左往右扫描中缀表达式
     * 3. 遇到操作数时,直接压s2
     * 4. 遇到运算符时,比较其与s1栈顶运算符的优先级
     *	4.1 如果s1为空,或栈顶运算符为左括号"(",则直接将此运算符入栈
     *  4.2 否则,若优先级比栈顶运算符的高,也将运算符压入s1
     *  4.3 否则,将s1栈顶的运算符弹出并压入s2中,再次转到4.1与s1中新的栈顶运算符相比较
     * 5. 遇到括号时
     *  5.1 如果是左括号"(",则直接压入s1
     *  5.2 如果是右括号")",则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号位置,此时将这一对括号丢弃
     * 6. 重复步骤2-5,直到表达式的最右边
     * 7. 将s1中剩于的运算符依次弹出并压入s2
     * 8. 终止
     * 将listExpression转逆波兰表达式,转好的字符串应该带空格隔开
     */
    public static void main(String[] args) {
        String expr = "(3*6-9)*2*(4-3)+9-8";
        //转成逆波兰表达式字符串,空格隔开
        String suffixStr = exprToSuffix(expr);
        //计算逆波兰表达式
        int res = calculateExpr(suffixStr);
        System.out.printf("表达式%s = %d\n", expr, res);
    }
    public static int calculateExpr(String expr) {
        //得到的expr的形式如:"3 4 1 - 8 * + 2 + 8 - 8 4 / + 10 10 * - "
        ArrStack arrStack = new ArrStack(20);
        int num1, num2;
        for(String item: expr.split(" ")) {
            if(item.matches("\\d+")) { // 匹配的是多位数字
                arrStack.push(Integer.parseInt(item));
            }
            else { // 匹配的是操作符
                num2 = arrStack.pop();
                num1 = arrStack.pop();
                arrStack.push(arrStack.calculate(num1, num2, item.charAt(0)));
            }
        }
        return arrStack.pop();
    }
    public static String exprToSuffix(String expr) {
        //先写一个将此中缀表达式转逆波兰表达式所需要的符号栈
        String res = ""; // 用于接收最终需要的逆波兰表达式的字符串,用空格隔开
        int index = 0;
        //扫描此表达式
        char ch = ' ';
        ArrStack stack = new ArrStack(30);
        while(index < expr.length()) {
            if(isOpe(ch = (expr.substring(index, index + 1).charAt(0)))) { // 扫描到运算符
                while(true) {
                    if(stack.isEmpty() || stack.peek() == '(' || stack.priority(stack.peek()) < stack.priority(ch)) {
                        stack.push(ch);
                        break;
                    }
                    res = res + (char)stack.pop() + " ";
                }
                index ++;
            }
            else if(isNum(ch)) { // 当前扫描到的是数字,那么还需要继续扫描直到不是数字
                while(index < expr.length() && isNum(ch)) {
                    res = res + ch;
                    index ++;
                    if(index < expr.length()) ch = expr.substring(index, index + 1).charAt(0);
                }
                res = res + " ";
            }
            else { // 扫描到的是括号
                if(ch == '(') stack.push(ch);
                else { // 遇到了右括号
                    while(stack.peek() != '(') {
                        res = res + (char)stack.pop() + " ";
                    }
                    stack.pop(); // 弹出没用的左括号
                }
                index ++;
            }
        }
        while(!stack.isEmpty()) {
            res = res + (char)stack.pop() + " ";
        }
        return res;
    }
    public static boolean isOpe(char ch) {
        return ch == '+' || ch == '-' || ch == '*' || ch == '/';
    }
    public static boolean isNum(char ch) {
        return ch >= 48 && ch <= 57;
    }

}
class ArrStack {
    private int[] arr;
    private int maxSize;
    private int rear;
    public ArrStack(int maxSize) {
        this.maxSize = maxSize;
        arr = new int[maxSize];
        rear = -1;
    }
    public boolean isEmpty() {
        return rear == -1;
    }
    public boolean isFull() {
        return rear == maxSize - 1;
    }
    public void push(int ele) {
        if(isFull()) {
            System.out.println("栈已满,无法加入新元素~~");
            return;
        }
        arr[++ rear] = ele;
    }
    public int pop() {
        if(isEmpty())
            throw new RuntimeException("栈为空,无法pop出元素~~");
        return arr[rear --];
    }
    public int peek() {
        if(isEmpty())
            throw new RuntimeException("栈为空,无法peek~~");
        return arr[rear];
    }
    public void showData() {
        if(isEmpty()) {
            System.out.println("栈为空,没有元素可show~~");
            return;
        }
        for (int i = 0; i <= rear; i++) {
            System.out.printf("arr[%d] = %d\t", i, arr[i]);
        }
        System.out.println();
    }
    public int priority(int ope) {
        return (ope == '*' || ope == '/')? 1: 0;
    }
    public int calculate(int num1, int num2, char ope) {
        switch (ope) {
            case'+':
                return num1 + num2;
            case'-':
                return num1 - num2;
            case'*':
                return num1 * num2;
            case'/':
                return num1 / num2;
            default:
                throw new RuntimeException("操作符错误~~请检查");
        }
    }
}

走迷宫的问题

public class MazeSolution {
    public static void main(String[] args) {
        int[][] map = new int[8][7]; // 大小为8*7的迷宫
        initialMap(map);
        printArray(map);
        setWay(map, 1, 1);
        printArray(map);
    }
    //初始化地图
    public static void initialMap(int[][] map) {
        /**
         * 用0表示可以走的路
         * 用1表示墙体
         * 用2表示已经走过的路
         * 用3表示这条路已经走多了而且走不通
         */
        //上下全部置为1
        for(int i = 0; i < map[0].length; i++){
            map[0][i] = 1;
            map[map.length - 1][i] = 1;
        }
        //左右全部置1
        for(int i = 1; i < map.length - 1; i++){
            map[i][0] = 1;
            map[i][map[0].length - 1] = 1;
        }
        //设置挡板
        map[3][1] = 1;
        map[3][2] = 1;
        map[2][3] = 1;
        map[2][2] = 1;
        map[4][5] = 1;
        map[5][3] = 1;
        map[5][4] = 1;
    }
    //打印地图
    public static void printArray(int [][] arr) {
        System.out.println("地图的情况~~");
        for(int[] row:arr){
            for(int ele:row){
                System.out.print(ele + " ");
            }
            System.out.println();
        }
    }
    /**
     * @param map 表示地图
     * @param i j 从地图哪个位置开始出发找路
     * @return 找到通路就返回true,否则返回false
     * 走到地图的map[-1][-1]时代表到达终点
     * 确定一个策略方法,下>右>上>左,如果该点走不通则回溯
     */
    public static boolean setWay(int[][] map, int i, int j) {
        if(map[map.length - 2][map[0].length - 2] == 2) return true;
        //当前这个点没有被走过
        if(map[i][j] == 0) {
            map[i][j] = 2; //标记已经走过了
            if(setWay(map, i + 1, j) || setWay(map, i, j + 1) || setWay(map, i - 1, j) || setWay(map, i, j - 1)) {
                return true;
            }
            map[i][j] = 3;
        }
        return false;
    }
    //完整版
    /*
    public static boolean setWay(int [][]map, int i, int j){
        if(map[map.length - 2][map[0].length - 2] == 2){//通路已经找到
            return true;
        }
        else{
            if(map[i][j] == 0){//当前这个点还没有走过
                //按照策略,下>右>上>左
                map[i][j] = 2;//确定该点可以走通
                if(setWay(map, i+1, j)){//向下走
                    return true;
                }else if(setWay(map, i, j+1)){//向右走
                    return true;
                }else if(setWay(map, i-1, j)){//向上走
                    return true;
                }else 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 class Queen8 {
    static int max = 8;
    static int count = 0; // 表示一共有多少种放置的方法
    static int[] queenArray = new int[max];
    public static void main(String[] args) {
        //先创建一个8*8的格子用于记录皇后摆放
        /**
         * 用一个一维数组即可解决该问题
         * [0, 4, 7, 5, 2, 6, 1, 3] 其中第1个皇后放在第1行第1列
         * 第2个皇后放在第2行第5列...第8个皇后放在第8行第4列
         */
        playQueen(0);
        System.out.println(count);
    }
    //打印出皇后摆放的位置
    public static void printQueenLocation(){
        for(int elem:queenArray){//都要设置成static才能访问queenArray
            System.out.print(elem + " ");
        }
        System.out.println();
    }
    //放置第n个皇后的位置
    public static void playQueen(int n) {
        if(n == max) {
            count ++;
            printQueenLocation();
            return;
        } // 表示前0-7个已经放完了,想放第8个时游戏结束
        for (int i = 0; i < max; i++) {
            queenArray[n] = i; // 先把这个皇后放在这个位置再判断是否冲突,如果不冲突,那么放下一个
            if(judgeConflict(n)) {
                playQueen(n + 1);
            }
        }
    }
    //判断这个皇后的位置是否与前面的冲突
    public static boolean judgeConflict(int i) {
        for(int j = 0; j < i; j++) {
            if(queenArray[i] == queenArray[j] || (i - j) == Math.abs(queenArray[i] - queenArray[j])) return false;
        }
        return true;
    }
}

冒泡排序算法

	//冒泡排序
    public static void popSort(int[] arr) {
        int n = arr.length;
        //n个数要经过n-1轮排序
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                if(arr[j] > arr[j + 1]) swap(arr, j, j + 1);
            }
        }
    }

选择排序算法

	public static void selectSort(int[] arr) {
        int n = arr.length;
        int max, index;
        for (int i = n - 1; i > 0; i--) { // 先与最后一个数进行交换,即找最大的数
            max = arr[0];
            index = 0;
            for (int j = 1; j < i + 1; j++) {
                if(max < arr[j]) {
                    max = arr[j];
                    index = j;
                }
            }
            swap(arr, i, index);
        }
    }

插入排序算法

	public static void insertSort(int[] arr) {
        int n = arr.length;
        for (int i = 1; i < n; i++) { // 假设的是第0个元素为有序
            int ele = arr[i], index = i; // 将要插入的这个元素保存起来
            for (int j = i - 1; j >= 0; j--) {
                if(arr[j] > ele) {
                    arr[j + 1] = arr[j];
                    index = j;
                }
                else break;
            }
            arr[index] = ele;
        }
    }

希尔排序

	public static void xerSort(int[] arr) {
        int n = arr.length;
        for (int foot = n / 2; foot > 0; foot /= 2) {
            for (int j = foot; j < n; j ++) {
                int index = j;
                int ele = arr[j];
                for (int i = j - foot; i >= 0; i -= foot) {
                    if(arr[i] > ele) {
                        index = i;
                        arr[i + foot] = arr[i];
                    }
                    else break;
                }
                arr[index] = ele;
            }
        }
    }

快速排序算法

	public static void quickSort(int[] arr, int left, int right) {
        if(left >= right) return;
        //取最左边的数为基准数
        int baseVal = arr[left];
        int i = left, j = right;
        while(i < j) {
            //右边的j先动
            while(i < j && arr[j] >= baseVal) {
                j --;
            }
            while(i < j && arr[i] <= baseVal) {
                i ++;
            }
            if(i == j) swap(arr, left, i);
            else swap(arr, i, j);
        }
        quickSort(arr, left, i - 1);
        quickSort(arr, i + 1, right);
    }

归并排序算法

	//归并排序
    public static void mergeSort(int[] arr) {
        int[] temp = new int[arr.length];
        divide(arr, 0, arr.length - 1, temp);
    }
    //分
    public static void divide(int[] arr, int left, int right, int[] temp) {
        if(left < right) {
            int mid = (left + right) / 2;
            divide(arr, left, mid, temp);
            divide(arr, mid + 1, right, temp);
            merge(arr, left, mid + 1, right, temp);
        }
    }
    //治
    public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        int l = left, m = mid;
        int tIndex = 0;
        while(l < mid && m <= right) {
            temp[tIndex ++] = (arr[l] < arr[m])?arr[l ++]:arr[m ++];
        }
        while(l < mid) {
            temp[tIndex ++] = arr[l ++];
        }
        while(m <= right) {
            temp[tIndex ++] = arr[m ++];
        }
        tIndex = 0;
        //将temp数组拷贝回原始数组
        int index = left;
        while(index <= right) {
            arr[index ++] = temp[tIndex ++];
        }
    }

还剩一种基数排序算法就明天再复习啦~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值