数据结构和算法(2)

2.1栈

栈(stack),也称堆栈,是一种操作受限的线性表,栈只允许在线性表的一端进行操作。

在线性表中进行操作的一端叫栈顶(top),栈顶保存的元素叫栈顶元素,相对一端叫栈底(bottom)。

栈的操作只允许在栈顶操作,元素先入后出。(First In Last Out简称FILO)

如果没有元素称为空栈。

向栈中插入元素叫进栈或入栈,删除元素叫退栈或出栈。

/**
* @author Rose
* @Email 510130303@qq.com
* @date 2020/8/6 9:59
 * 定义栈的操作
*
*/
public interface MyStack {
    int getSize();          //返回元素个数
    boolean isEmpty();      //判断是否为空
    void push(Object e);    //压栈
    Object pop();           //弹栈
    Object peek();          //返回栈顶元素
}

2.1.1栈的顺序存储

//堆栈的顺序实现
public class MyArrayStack implements MyStack {
    private Object[] elements;      //数组存储堆栈元素
    private static final int DEFAULT_CAPACITY = 16;     //数组默认大小
    private int top;        //栈顶指针

    //默认构造
    public MyArrayStack(){
        elements = new Object[DEFAULT_CAPACITY];
    }

    //有参构造,给数组赋予大小
    public MyArrayStack(int initialCapacity){
        elements = new Object[initialCapacity];
    }

    //返回堆栈大小
    @Override
    public int getSize() {
        return top;
    }

    //判断堆栈是否为空
    @Override
    public boolean isEmpty() {
        return top <= 0;
    }

    //入栈
    @Override
    public void push(Object e) {
        //判断堆栈是否已满
        //已满,数组扩容
        if (top >= elements.length){
            //定义一个是原来2倍大的新数组
            Object[] newElements = new Object[elements.length * 2];
            //把旧数组内容复制到新数组
            for (int i = 0;i < elements.length;i++){
                newElements[i] = elements[i];
            }
            //让原来的旧数组指向新数组
            elements = newElements;
        }
        //把 e 存入栈顶位置
        elements[top] = e;
        //栈顶指针修改指向
        top++;
    }

    //出栈
    @Override
    public Object pop() {
        //判断堆栈是否为空
        if (top <= 0){
            throw new StackOverflowError("栈已空");
        }
        top--;
        return elements[top];
    }

    //返回栈顶元素
    @Override
    public Object peek() {
        //判断堆栈是否为空
        if (top <= 0){
            throw new StackOverflowError("栈已空");
        }
        return elements[top-1];
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        //从栈顶到栈底顺序遍历
        for (int i = top-1;i >= 0;i--){
            sb.append(elements[i]);
            if (i > 0){
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}
public class MyArrayStackTest {
    public static void main(String[] args) {
        MyArrayStack myArrayStack = new MyArrayStack();
        //返回堆栈大小
        System.out.println(myArrayStack.getSize());
        //判断堆栈是否为空
        System.out.println(myArrayStack.isEmpty());
        //入栈
        myArrayStack.push("飞");
        myArrayStack.push("云");
        myArrayStack.push("沈");
        System.out.println(myArrayStack.getSize());
        System.out.println(myArrayStack.isEmpty());
        System.out.println(myArrayStack);
        //弹栈
        Object pop = myArrayStack.pop();
        System.out.println(pop);
        System.out.println(myArrayStack);
        //返回栈顶元素
        Object peek = myArrayStack.peek();
        System.out.println(peek);


    }
}

2.1.2栈的链式存储 

也称链栈

栈只允许在线性表的一端操作,可以选择链表的首结点作为栈顶,操作都在首结点上进行。

//栈的链式存储
public class MyLinkedStack implements MyStack {
    private Node top;        //存储栈顶指针的引用
    private int size;       //存储堆栈中的元素个数

    //内部类,描述链表的结点
    private class Node{
         Object data;        //存储数据
         Node next;         //存储下一个结点引用

        public Node(Object data, Node next) {
            this.data = data;
            this.next = next;
        }
    }

    //返回堆栈大小
    @Override
    public int getSize() {
        return size;
    }

    //判断堆栈是否为空
    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    //入栈
    @Override
    public void push(Object e) {
        //创建新结点,插入到链表头部
        Node pNode = new Node(e,top);
        //修改top指针指向新结点
        top = pNode;
        size++;
    }

    //出栈
    @Override
    public Object pop() {
        //判断堆栈是否为空
        if (size < 1){
            throw  new StackOverflowError("栈已空");
        }
        Object old = top.data;      //旧数据
        top = top.next;             //栈顶指针后移
        size--;
        return old;
    }

    //返回栈顶元素
    @Override
    public Object peek() {
        //判断堆栈是否为空
        if (size < 1){
            throw  new StackOverflowError("栈已空");
        }
        return top.data;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (Node pNode = top;pNode != null;pNode = pNode.next){
            sb.append(pNode.data);
            if (pNode.next != null){
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}
public class MyLinkedStackTest {
    public static void main(String[] args) {
        MyLinkedStack myLinkedStack = new MyLinkedStack();
        //插入
        myLinkedStack.push("飞");
        myLinkedStack.push("云");
        myLinkedStack.push("沈");
        //大小
        System.out.println(myLinkedStack.getSize());
        //为空
        System.out.println(myLinkedStack.isEmpty());
        System.out.println(myLinkedStack);
        //栈顶元素
        System.out.println(myLinkedStack.peek());
    }
}

2.1.3栈的应用

一 将十进制整数转换成任意进制数

/**
* @author Rose
* @Email 510130303@qq.com
* @date 2020/8/7 8:55
 * 将十进制整数num转换成decimal指定进制数
*
*/
public class MyArrayStackUtils {
    public static void main(String[] args) {
        System.out.println(convert(100,2));
        System.out.println(convert(100,8));
        System.out.println(convert(100,16));
    }
    public static String convert(int num,int decimal){
        MyArrayStack myArrayStack = new MyArrayStack();     //保存余数
        int remainder = num % decimal;                       //计算余数
        while (num != 0){
            myArrayStack.push(remainder);                    //余数压栈
            num = num / decimal;
            remainder = num % decimal;
        }
        StringBuilder sb = new StringBuilder();
        while (!myArrayStack.isEmpty()){
            sb.append(myArrayStack.pop());                   //弹栈
        }
        return sb.toString();
    }
}

二 匹配括弧

/**
* @author Rose
* @Email 510130303@qq.com
* @date 2020/8/7 9:16
 * 括弧匹配
*
*/
public class BracketMatch {
    public static void main(String[] args) {
        System.out.println(bracketMatch("[{()}]"));
        System.out.println(bracketMatch("{{))"));
    }

    //检测表达式expression中的括弧是否合法
    public static boolean bracketMatch(String expression){
        MyArrayStack myArrayStack = new MyArrayStack();     //保存左括弧
        //遍历整个表达式,如果是左括弧就入栈,如果是右括弧,就出栈
        for (int i = 0;i < expression.length();i++){
            //取出每个字符
            char c = expression.charAt(i);
            switch (c) {
                case '(':
                case '[':
                case '{':
                    myArrayStack.push(c);
                    break;
                case ')':
                    //如果栈不为空,且弹栈的元素和左括弧一样,则成功
                    if (!myArrayStack.isEmpty() && myArrayStack.pop().equals('(')){
                        break;
                    }else return false;
                case ']':
                    if (!myArrayStack.isEmpty() && myArrayStack.pop().equals('[')){
                        break;
                    }else return false;
                case '}':
                    if (!myArrayStack.isEmpty() && myArrayStack.pop().equals('{')){
                        break;
                    }else return false;
            }
        }
        if (myArrayStack.isEmpty()){
            return true;
        }else return false;
    }
}

3.1队列

3.1.1队列的顺序存储

/**
* @author Rose
* @Email 510130303@qq.com
* @date 2020/8/7 10:54
 * 队列的顺序存储
*
*/
public class MyArrayQueue {
    private Object[] elements;  //存储队列元素
    private static final int DEFAULT_CAPACITY = 8;      //数组默认大小
    private int front;      //队首
    private int rear;       //队尾
    private int size;       //元素个数

    //有参构造
    public MyArrayQueue() {
        elements = new Object[DEFAULT_CAPACITY];
    }

    //无参构造
    public MyArrayQueue(int initialCapacity) {
        elements = new Object[initialCapacity];
    }

    //返回元素个数
    public int getSize(){
        return size;
    }

    //判断是否为空
    public boolean isEmpty(){
        return size == 0;
    }

    //入队
    public void enQueue(Object e){
        //如果数组已满,扩容
        if (size >= elements.length){
            expandQueue();
        }
        elements[rear] = e;     //元素存储到rear所指位置
        rear = (rear + 1) % elements.length;    //指针后移
        size++;
    }
    //出队
    public Object deQueue(){
        //队列为空,异常
        if (size <= 0){
            throw new QueueRuntimeException("队列为空");
        }
        //队列不为空,返回front所指元素
        Object old = elements[front];
        //后移
        front = (front + 1) % elements.length;
        size--;
        return old;
    }

    //返回首元素
    public Object peek(){
        //队列为空
        if (size <= 0){
            throw new QueueRuntimeException("队列为空");
        }
        return elements[front];
    }
    //数组扩容
    private void expandQueue() {
        //创建一个长度是原来2倍的新数组
        Object[] newElements = new Object[elements.length * 2];
        //将旧数组复制到新数组中去
        for (int i = 0;i < size;i++){
            newElements[i] = elements[front];
            front = (front + 1) % elements.length; //后移
        }
        //修改旧数组指向新数组
        elements = newElements;
        //调整队首队尾指针
        front = 0;
        rear = size;
    }

    public String toString(){
        if (size <= 0){
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0;i < size;i++){
            sb.append(elements[front]);
            front = (front + 1) % elements.length;
            if (rear != front){
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    //异常内部类
    class QueueRuntimeException extends RuntimeException {
        public QueueRuntimeException() {
            super();
        }

        public QueueRuntimeException(String message) {
            super(message);
        }
    }
}
public class MyArrayQueueTest {
    public static void main(String[] args) {
        MyArrayQueue myArrayQueue = new MyArrayQueue(3);
        System.out.println(myArrayQueue.getSize());
        System.out.println(myArrayQueue.isEmpty());
        myArrayQueue.enQueue("沈");
        myArrayQueue.enQueue("云");
        myArrayQueue.enQueue("飞");
        System.out.println(myArrayQueue);
        System.out.println(myArrayQueue.peek());
        myArrayQueue.deQueue();
        myArrayQueue.deQueue();
        System.out.println(myArrayQueue);
        myArrayQueue.deQueue();
        System.out.println(myArrayQueue);
       // myArrayQueue.deQueue();

    }
}

3.1.2队列的链式存储

/**
* @author Rose
* @Email 510130303@qq.com
* @date 2020/8/7 16:23
 * 队列的连式存储
*
*/
public class MyLinkedQueue {

    private Node front;     //队首
    private Node rear;      //队尾
    private int size;       //元素个数

    //内部类
    private class Node{
        Object element;
        Node next;

        public Node(Object element, Node next) {
            this.element = element;
            this.next = next;
        }
    }

    //返回元素个数
    public int getSize(){
        return size;
    }

    //判断队列是否为空
    public boolean isEmpty(){
        return size == 0;
    }

    //入队
    public void enQueue(Object e){
        //生成一个结点
        Node newNode = new Node(e, null);
        //把结点添加到队列中
        //如果 rear 为null,那么这是一个空队列
        if (rear == null){
            front = newNode;
            rear = newNode;
        }else {
            //如果 raer 不为空,那么添加新结点到 队尾rear的下一个结点
            rear.next = newNode;
            //修改队尾指向
            rear = newNode;
        }
        //元素个数增加
        size++;
    }
    //出队
    public Object deQueue(){
        //判断队列是否为空
        if (size <= 0){
            throw new QueueRuntimeException("队列为空");
        }
        //存储旧数据
        Object old = front.element;
        //指针后移
        front = front.next;
        //出队之后,队空了,调整队尾指针
        if (front == null){
            rear = null;
        }
        //元素数量降低
        size--;
        return old;
    }

    //返回队首元素
    public Object peek(){
        return front.element;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        //队尾空,返回null
        if (size <= 0){
            return null;
        }
        for (Node pNode = front;pNode != null;pNode = pNode.next){
            sb.append(pNode.element);
            if (pNode.next != null){
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    //异常内部类
     class QueueRuntimeException extends RuntimeException {
        public QueueRuntimeException() {
            super();
        }

        public QueueRuntimeException(String message) {
            super(message);
        }
    }
}
public class MyLinkedQueueTest {
    public static void main(String[] args) {
        MyLinkedQueue myLinkedQueue = new MyLinkedQueue();
        System.out.println(myLinkedQueue.getSize());
        System.out.println(myLinkedQueue.isEmpty());
        myLinkedQueue.enQueue("沈");
        myLinkedQueue.enQueue("云");
        myLinkedQueue.enQueue("飞");
        System.out.println(myLinkedQueue);
        System.out.println(myLinkedQueue.getSize());
        System.out.println(myLinkedQueue.isEmpty());
        System.out.println(myLinkedQueue.peek());
    }
}

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值