厚积薄发打卡Day111:堆栈实践(一)<数组模拟堆栈、链表模拟堆栈、洗牌与发牌的过程>

厚积薄发打卡Day111:堆栈实践(一)<数组模拟堆栈、链表模拟堆栈、洗牌与发牌的过程>

堆栈知识回顾:

剑指offer打卡Day18 栈的压入、弹出序列(重新学习 Vector 与 Stack)

时隔一年重写博客,用一道简单的例题回顾下所学知识

题目描述

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

示例

  • 输入
    • [1,2,3,4,5],[4,3,5,1,2]
  • 返回值
    • false

具体解题及相关知识回顾都在之前的文章中(剑指offer打卡Day18 栈的压入、弹出序列(重新学习 Vector 与 Stack))感兴趣的读者可自行跳转查看,下面列举下大体思路:

大体思路:

  1. 将目标数据压入栈中:targetStack ==> || 1< 2< 3 < 4 < 5
  2. 在压入栈的过程中,用指针遍历待验证的数组 arrayData = > [4,3,5,1,2],若数组元素与压栈元素一致,则说明arrayData中的元素可以通过弹栈实现

代码验证:

public class IsPopOrderTest {

    private static boolean IsPopOrder(int[] pushA, int[] popA) {
        // 非空判断:
        if (pushA.length == 0 || popA.length == 0) {
            return false;
        }
        // 辅助栈,存入栈数据:
        Stack<Integer> assistStack = new Stack<>();
        // 弹栈验证指针位置
        int popTarget = 0;
        for (int i : pushA) {
            assistStack.push(i);
            // 如果栈顶不为空,且栈顶元素等于弹出序列
            while (!assistStack.empty() && assistStack.peek() == popA[popTarget]) {
                // 出栈
                assistStack.pop();
                //弹出序列向后一位
                popTarget++;
            }
        }
        return assistStack.empty();
    }

    public static void main(String[] args) {
        int[] intA = {1, 2, 3, 4, 5};
        int[] intB = {4, 3, 5, 1, 2};
        System.out.println(IsPopOrder(intA, intB));
    }
}

数组模拟堆栈

请使用数组结构来设计一个Java程序,并使用循环来控制准备压入或者弹出的元素,并仿真堆栈的各种操作,其中必须包括压入(push)与弹出(pop)函数,最后还要输出堆栈内的所有元素

/**
 * 用数组模拟堆栈
 */
public class StackByArray {
    // 类中的数组
    private int[] stack;
    // 顶端索引
    private int top;

    public StackByArray(int stackSize) {
        stack = new int[stackSize];
        top = 0;
    }

    // push
    public boolean push(int data) {
        // 判断是否有位置
        if (top > stack.length) {
            System.out.println("堆栈已满,无法再压入");
            return false;
        } else {
            stack[top] = data;
            top++;
            return true;
        }
    }

    // empty
    public boolean empty() {
        return top == 0;
    }

    // pop
    public int pop() {
        if (empty()) {
            return -1;
        } else {
            return stack[--top];
        }
    }

    public static void main(String[] args) {
        StackByArray stack = new StackByArray(10);
        Random random = new Random();
        System.out.println("随机入栈:" );
        for (int i = 0; i < 10; i++) {
            int i1 = random.nextInt(100);
            System.out.print(i1);
            System.out.print(" >> ");
            stack.push(i1);
        }
        System.out.println();
        System.out.println("弹栈顺序为:");
        while (!stack.empty()) {
            System.out.print(stack.pop());
            System.out.print(" << ");
        }
    }
}
随机入栈:
95 >> 56 >> 63 >> 18 >> 17 >> 48 >> 45 >> 90 >> 38 >> 10 >> 
弹栈顺序为:
10 << 38 << 90 << 45 << 48 << 17 << 18 << 63 << 56 << 95 << 

链表模拟堆栈

请设计一个Java程序,以链表来实现堆栈操作,并使用循环来控制准备压入或者弹出的元素,并仿真堆栈的各种操作,其中必须包括压入(push)与弹出(pop)函数,最后还要输出堆栈内的所有元素

思路模拟

          ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ 
stack :  |                             <- 入栈      
          ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
          ↑                      ↑
         front                   rear

代码实现:

package stack.stack20230101;

import java.util.Random;

/**
 * 链表实现堆栈(类似双指针队列)
 */
public class StackByLink {
    // 链表节点的声明
    class Node {
        int data;
        Node next;

        public Node(int data) {
            this.data = data;
            this.next = null;
        }

    }

    // 栈底的指针
    public Node front;

    // 栈顶的指针
    public Node rear;

    // 判空:empty
    public boolean isEmpty() {
        return front == null;
    }

    // 打印:
    public void output_of_Stack() {
        Node current = front;
        while (current != null) {
            System.out.print("[" + current.data + "]");
            current = current.next;
        }
        System.out.println();
    }

    // 入栈:
    public void insert(int data) {
        Node node = new Node(data);
        if (isEmpty()) {
            front = node;
            rear = node;
        } else {
            // todo 重点理解
            rear.next = node;
            rear = node;
        }
    }

    // 弹栈:
    public void pop() {
        Node newNode;
        if (isEmpty()) {
            System.out.println("当前堆栈为空");
            return;
        }
        newNode = front;
        if (newNode == rear) {
            front = null;
            rear = null;
            System.out.println("当前堆栈为空");
        } else {
            while (newNode.next != rear) {
                newNode = newNode.next;
            }
            newNode.next = rear.next;
            rear = newNode;

        }
    }

    public static void main(String[] args) {
        StackByLink stackByLink = new StackByLink();
        Random random = new Random();
        System.out.println("入栈:");
        for (int i = 0; i < 10; i++) {
            int i1 = random.nextInt(100);
            System.out.print("<<" + i1 );
            stackByLink.insert(i1);
        }
        System.out.println();
        System.out.println("压入堆栈后:");
        stackByLink.output_of_Stack();
        System.out.println("弹栈:");
        while (!stackByLink.isEmpty()) {
            stackByLink.pop();
            stackByLink.output_of_Stack();
        }
    }
}
入栈:
<<67<<21<<55<<21<<67<<93<<32<<59<<95<<64
压入堆栈后:
[67][21][55][21][67][93][32][59][95][64]
弹栈:
[67][21][55][21][67][93][32][59][95]
[67][21][55][21][67][93][32][59]
[67][21][55][21][67][93][32]
[67][21][55][21][67][93]
[67][21][55][21][67]
[67][21][55][21]
[67][21][55]
[67][21]
[67]
当前堆栈为空

堆栈模拟洗牌发牌

请设计一个Java程序,用数组仿真扑克牌洗牌及发牌的过程。请用随机数来生成扑克牌后压入堆栈,放满52张牌后开始发牌,使用堆栈的弹出功能给四个人发牌。

package stack.stack20230101;

/**
 * 洗牌与发牌全过程:
 * 0~12 梅花♣
 * 13~25 方块♦
 * 26~38 红桃♥
 * 39~51 黑桃♠
 */
public class StackShuffle {

    static int top = -1;

    public static void main(String[] args) {
        int[] card = new int[52];
        int[] stack = new int[52];

        int i, j, k = 0, test;
        char ascVal = 5;
        int style;
        for (i = 0; i < 52; i++) {
            card[i] = i;
        }
        System.out.println("[洗牌中......请稍后!]");
        while (k < 30) {
            for (i = 0; i < 51; i++) {
                for (j = i + 1; j < 52; j++) {
                    if (((int) (Math.random() * 5)) == 2) {
                        test = card[i];//洗牌
                        card[i] = card[j];
                        card[j] = test;
                    }
                }
            }
            k++;
        }
        i = 0;
        while (i != 52) {
            push(stack, card[i]);
            i++;
        }
        System.out.println("[逆时针发牌]");
        System.out.println("[显示各家的牌]\n 东家\t 北家\t 西家\t 南家\t");
        System.out.println("========================================");
        while (top >= 0) {
            style = stack[top] / 13;
            switch (style) {
                case 0:
                    ascVal = '♣';
                    break;
                case 1:
                    ascVal = '♦';
                    break;
                case 2:
                    ascVal = '♥';
                    break;
                case 3:
                    ascVal = '♠';
                    break;
            }
            System.out.print("[" + ascVal + (stack[top] % 13 + 1) + "]");
            System.out.print("\t");
            if (top % 4 == 0) {
                System.out.println();
            }
            top--;
        }
    }

    private static void push(int[] stack, int val) {
        if (top >= 52 - 1) {
            System.out.println("[堆栈已满]");
        } else {
            top++;
            stack[top] = val;
        }
    }
}
[洗牌中......请稍后!]
[逆时针发牌]
[显示各家的牌]
 东家	 北家	 西家	 南家	
========================================
[♠12]	[♥9]	[♦10]	[♥6]	
[♥5]	[♣11]	[♣7]	[♥13]	
[♣12]	[♣3]	[♠3]	[♠8]	
[♥4]	[♦7]	[♥12]	[♠13]	
[♠6]	[♥10]	[♦6]	[♥8]	
[♥11]	[♦12]	[♦5]	[♣1]	
[♦4]	[♥3]	[♣2]	[♦8]	
[♦13]	[♦9]	[♠11]	[♣4]	
[♦1]	[♥1]	[♠5]	[♣8]	
[♣10]	[♣5]	[♠9]	[♦3]	
[♠10]	[♣9]	[♠2]	[♣6]	
[♦11]	[♥2]	[♣13]	[♠4]	
[♥7]	[♦2]	[♠1]	[♠7]	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值