重温数据结构:队列的链式实现、顺序实现及循环队列

1.队列的链式存储实现

队列接口:

package edu.njupt.zhb;
/*
 *@author: ZhengHaibo
 *web:     http://blog.csdn.net/nuptboyzhb
 *mail:    zhb931706659@126.com
 *2014-3-12  Nanjing,njupt,China
 */
public interface MyQueue {
	public void add(Object object);//从队列尾部加入一个元素
	public Object remove();//出列,返回队列头部的值,并将其删除
	public int getSize();//获取队列的大小
	public Object peek();//偷看队列的前端元素,但是不出列
	public boolean isEmpty();
}

链式存储的实现

/*
 * $filename: MyLinkedQueue.java,v $
 * $Date: 2014-3-12  $
 * Copyright (C) ZhengHaibo, Inc. All rights reserved.
 * This software is Made by Zhenghaibo.
 */
package edu.njupt.zhb;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

/*
 *@author: ZhengHaibo  
 *web:     http://blog.csdn.net/nuptboyzhb
 *mail:    zhb931706659@126.com
 *2014-3-12  Nanjing,njupt,China
 */
/**
 * 队列的链式实现
 */
public class MyLinkedQueue implements MyQueue{
	public class Node{
		Node next;
		Object data;
	}
	private Node front;//前面的指针
	private Node rear;//后面的指针
	private int size;
	public MyLinkedQueue(){
		front=new Node();
		front.next=null;
		rear=new Node();
		rear.next=null;
		size=0;
	}
	/**
	 * 入列,从尾部添加元素
	 */
	@Override
	public void add(Object object) {
		// TODO Auto-generated method stub
		Node node = new Node();
		node.data=object;
		if(size==0){//如果是空的
			front.next=node;
			rear.next=node;
			size++;
			return;
		}
		rear.next.next=node;//将尾节点指向新增节点
		rear.next=node;//将rear指针指向新增节点
		size++;
	}
	/**
	 * 出列,从头部取出元素,并删除
	 */
	@Override
	public Object remove() {
		// TODO Auto-generated method stub
		if(front.next!=null){
			Object object=front.next.data;//取出当前队列的头元素
			front.next=front.next.next;//删除第一个元素
			size--;
			return object;
		}
		return null;
	}
	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return size;
	}
	
	@Override
	public Object peek() {
		// TODO Auto-generated method stub
		return front.next.data;
	}
	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		return size==0;
	}
	public static void main(String[] args) {
		MyQueue queue = new MyLinkedQueue();
		for(int i=0;i<20;i++){
			queue.add("str"+i);
		}
		while(!queue.isEmpty()){
			Object object=queue.remove();
			System.out.println((String)object);
		}
	}
}

队列的顺序存储:

/*
 * $filename: MyArrayQueue.java,v $
 * $Date: 2014-3-12  $
 * Copyright (C) ZhengHaibo, Inc. All rights reserved.
 * This software is Made by Zhenghaibo.
 */
package edu.njupt.zhb;
/*
 *@author: ZhengHaibo  
 *web:     http://blog.csdn.net/nuptboyzhb
 *mail:    zhb931706659@126.com
 *2014-3-12  Nanjing,njupt,China
 */
public class MyArrayQueue implements MyQueue {

	private int size;
	private int front;
	private int rear;
	final int INIT_LEN=10;//初始化长度
	final int INCREAMENT_LEN=10;//长度增量大小
	Object []objects;//用数组保存队列中的元素
	public MyArrayQueue(){
		size=0;
		front=0;
		rear=-1;
		objects = new Object[INIT_LEN];
	}
	@Override
	public void add(Object object) {
		// TODO Auto-generated method stub
		if(size+1==objects.length){//扩充数组
			Object []temp = new Object[objects.length+INCREAMENT_LEN];
			for(int i=0;i<objects.length;i++){
				temp[i]=objects[i];
			}
			objects=temp;
		}
		objects[++rear]=object;//将元素添加在队列的尾部
		size++;
	}

	@Override
	public Object remove() {
		// TODO Auto-generated method stub
		if(size==0){
			return null;
		}
		Object object = objects[front];//取出队列的头元素
		for(int i=0;i<objects.length-1;i++){//通过平移,删除已取出的元素
			objects[i]=objects[i+1];
		}
		size--;
		return object;
	}

	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return size;
	}

	@Override
	public Object peek() {
		// TODO Auto-generated method stub
		if(size==0){
			return null;
		}
		Object object = objects[front];//取出队列的头元素
		return object;
	}
	
	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		return size==0;
	}
	public static void main(String[] args) {
		MyQueue queue = new MyArrayQueue();
		for(int i=0;i<20;i++){
			queue.add("str"+i);
		}
		while(!queue.isEmpty()){
			Object object=queue.remove();
			System.out.println((String)object);
		}
	}
}

循环队列:

原因:主要是解决队列的“假溢出”问题。其实上面的顺序实现方式已经有效避免了假溢出(通过平移的方式)。下面来看一下循环队列吧。

/*
 * $filename: MyArrayCircularQueue.java,v $
 * $Date: 2014-3-12  $
 * Copyright (C) ZhengHaibo, Inc. All rights reserved.
 * This software is Made by Zhenghaibo.
 */
package edu.njupt.zhb;
/*
 *@author: ZhengHaibo  
 *web:     http://blog.csdn.net/nuptboyzhb
 *mail:    zhb931706659@126.com
 *2014-3-12  Nanjing,njupt,China
 */
/**
 *实现循环队列操作:
 (1)为使入队和出队实现循环,可以利用取余运算符%
 (2)队头指针进一:front=(front+1) % maxSize
 (3)队尾指针进一:rear=(rear+1) % maxSize
 (4)空队列:当front==rear 时为空队列
 (5)满队列:当(rear+1) % maxSize ==front时为满队列。满队列时实际仍有一个元素的空间未使用。
 */
public class MyArrayCircularQueue implements MyQueue {

	private int front;
	private int rear;
	private final int maxSize = 10;
	private Object []objects;
	private int size;
	public MyArrayCircularQueue(){
		front=rear=0;
		size=0;
		objects=new Object[maxSize];
	}
	@Override
	public void add(Object object) {
		// TODO Auto-generated method stub
		if((rear+1)%maxSize==front){
			System.out.println("队列已满...");
			return;
		}
		rear=(rear+1)%maxSize;
		objects[rear]=object;
		size++;
	}

	@Override
	public Object remove() {
		// TODO Auto-generated method stub
		if(front==rear){
			System.out.println("队列已经空了...");
			return null;
		}
		front=(front+1)%maxSize;
		Object object = objects[front];
		size--;
		return object;
	}

	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return size;
	}

	@Override
	public Object peek() {
		// TODO Auto-generated method stub
		return objects[front+1];
	}

	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		return front==rear;
	}
	
	public static void main(String[] args) {
		MyQueue queue = new MyArrayCircularQueue();
		for(int i=0;i<50;i++){
			queue.add("str"+i);
		}
		while(!queue.isEmpty()){
			Object object=queue.remove();
			System.out.println((String)object);
		}
	}
}

附录:


循环队列的示意图



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值