0
点赞
收藏
分享

微信扫一扫

Delphi中使用TXMLDocument对XML文件操作

我是芄兰 03-03 20:30 阅读 2

目录

一. 概念

二. 队列的使用

 三. 队列模拟实现

四. 循环队列

五. 面试题


一. 概念

队列 :只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为 队尾( Tail/Rear 出队列:进行删除操作的一端称为 队头 Head/Front

Java 中, Queue 是个接口,底层是通过链表实现 的。

在Queue接口的方法里, 我们看到有add remove element 这些是继承于Collection接口的, 而offer poll peek是接口本身的,他们的使用效果基本一致

二. 队列的使用

注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。 

 三. 队列模拟实现

队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,通过前面线性表的学习了解到常见的空间类型有两种:顺序结构 和 链式结构 。显然实现队列用链式结构更好, 但是用单链表还是双向链表呢?

如果使用单链表, 从队尾进, 想要找到队尾, 则需遍历一遍链表, 或需要用last指针指向队尾, 从队头出, 则需将头结点向后移动

显然, 使用双向链表更加方便.

(LinkedList 可以看做: 双向链表 栈 队列)

public class MyQueue {
    static class ListNode{
        public int val;
        public ListNode prev;
        public ListNode next;

        public ListNode(int val){
            this.val = val;
        }
    }
    public ListNode head;
    public ListNode last;
    //入队
    public void offer(int val){
        ListNode node = new ListNode(val);
        if(head == null){
            head = last = node;
        }else{
            last.next = node;
            node.prev = last;
            last = node;
        }
    }
    //出队
    public int poll(){
        if(empty()){
            return -1;
        }
        int val;
        if(head.next == null){
            val = head.val;
            head = null;
            last = null;
            return val;
        }
        val = head.val;
        head = head.next;
        head.prev = null;
        return val;

    }

    public boolean empty(){
        return head == null;
    }

    public int peek(){
        if(head ==null){
            return -1;
        }
        return head.val;
    }
}

四. 循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。

环形队列通常使用数组实现。

数组下标循环的小技巧

 

如何区分空与满

1. 通过添加 size 属性记录
2. 保留一个位置, 浪费一个空间

设计一个循环队列 链接

class MyCircularQueue {
    public int[] elem;
    public int front;
    public int rear;

    public MyCircularQueue(int k) {
        elem = new int[k+1];

    }
    //入队
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }
        elem[rear] = value;
        rear = (rear+1)%elem.length;
        return true;
    }
    //删除队头元素
    public boolean deQueue() {
       if(isEmpty()){
            return false;
        }
        front = (front + 1)%elem.length;
        return true;
    }
    //得到队头元素
    public int Front() {
        if(isEmpty()){
            return -1;
        }
        return elem[front];

    }
    //得到队尾元素
    public int Rear() {
        if(isEmpty()){
            return -1;
        }
         int index = (rear + elem.length - 1)%elem.length;
         return elem[index];

    }
    
    public boolean isEmpty() {
        return front == rear;

    }
    
    public boolean isFull() {
        return (rear + 1)%elem.length == front;
    }
}

五. 双端队列

双端队列( deque )是指允许两端都可以进行入队和出队操作的队列, deque “double ended queue” 的简称。

那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

 Deque是一个接口,使用时必须创建LinkedList的对象。

在实际工程中,使用 Deque 接口是比较多的,栈和队列均可以使用该接口。

五. 面试题

1. 用队列实现栈 链接

思路:一个队列是不能实现栈的, 需要用两个队列

1. 入栈, 当两个队列都为空时, 放在第一个队列里

2. 再次入栈时, 放在不为空的队列

3. 出栈时, 出不为空的队列, 出size-1个元素, 剩下的一个就是要出栈的元素

代码:

class MyStack {
    private Queue<Integer> qu1;
    private Queue<Integer> qu2;


    public MyStack() {
        qu1 = new LinkedList<>();
        qu2 = new LinkedList<>();

    }
    
    public void push(int x) {
        if(empty()){
            qu1.offer(x);
            return;
        }
        if(!qu1.isEmpty()){
            qu1.offer(x);
        }else{
            qu2.offer(x);
        }
    }
    
    public int pop() {
        if(empty()){
            return -1;
        }
        if(!qu1.isEmpty()){
            int size = qu1.size();
            for(int i = 0;i < size-1;i++){
                qu2.offer(qu1.poll());
            }
            return qu1.poll();
        }else{
            int size = qu2.size();
            for(int i = 0;i < size-1;i++){
                qu1.offer(qu2.poll());
            }
            return qu2.poll();
            
        }

    }
    
    public int top() {
          if(empty()){
            return -1;
        }
        if(!qu1.isEmpty()){
            int size = qu1.size();
            for(int i = 0;i < size-1;i++){
                qu2.offer(qu1.poll());
            }
            int tmp = qu1.peek();
            qu2.offer(qu1.poll());
            return tmp;
        }else{
            int size = qu2.size();
            for(int i = 0;i < size-1;i++){
                qu1.offer(qu2.poll());
            }
            int tmp = qu2.peek();
            qu1.offer(qu2.poll());
            return tmp;
        }

    }
    
    public boolean empty() {
        return qu1.isEmpty() && qu2.isEmpty();

    }
}

2. 用栈实现队列 链接

思路:一个栈不能实现队列, 需要两个栈

1. 入队, 把数据放在第一个栈

2. 出栈, 出第二个栈的栈顶元素即可, 如果第二个栈为空, 将里面的所有元素放到第二个栈

3. 当两个栈都为空时, 说明模拟的队列为空

class MyQueue {
    private Stack<Integer> s1;
    private Stack<Integer> s2;

    public MyQueue() {
        s1 = new Stack<>();
        s2 = new Stack<>();

    }
    
    public void push(int x) {
        s1.push(x);

    }
    
    public int pop() {
        if(empty()){
            return -1;
        }
        if(s2.isEmpty()){
            while(!s1.isEmpty()){
                s2.push(s1.pop());
            }
        }
        return s2.pop();

    }
    
    public int peek() {
        if(empty()){
            return -1;
        }
        if(s2.isEmpty()){
            while(!s1.isEmpty()){
                s2.push(s1.pop());
            }
        }
        return s2.peek();

    }
    
    public boolean empty() {
        return s1.isEmpty() && s2.isEmpty();

    }
}
举报

相关推荐

0 条评论