Java 模拟双端链表,以链表实现栈和队列

双端链表:

双端链表与传统链表非常相似.只是新增了一个属性-即对最后一个链结点的引用rear

这样在链尾插入会变得非常容易,只需改变rear的next为新增的结点即可,而不需要循环搜索到最后一个节点

所以有insertFirst、insertLast

删除链头时,只需要改变引用指向即可;删除链尾时,需要将倒数第二个结点的next置空,

而没有一个引用是指向它的,所以还是需要循环来读取操作

/**
 * 双端链表
 * @author stone
 */
public class TwoEndpointList<T> {
	private Link<T> head;		//首结点
	private Link<T> rear;		//尾部指针
	
	public TwoEndpointList() {
		
	}
	
	public T peekHead() {
		if (head != null) {
			return head.data;
		}
		return null;
	}
	
	public boolean isEmpty() {
		return head == null;
	}
	
	public void insertFirst(T data) {// 插入 到 链头
		Link<T> newLink = new Link<T>(data);
		newLink.next = head; //新结点的next指向上一结点
		head = newLink;
	}
	
	public void insertLast(T data) {//在链尾 插入
		Link<T> newLink = new Link<T>(data);
		if (head == null) {
			rear = null;
		}
		if (rear != null) {
			rear.next = newLink;
		} else {
			head = newLink;
			head.next = rear;
		}
		rear = newLink; //下次插入时,从rear处插入
		
	}
	
	public T  deleteHead() {//删除 链头
		if (isEmpty()) return null;
		Link<T> temp = head;
		head = head.next; //变更首结点,为下一结点
		if (head == null) {
		<span style="white-space:pre">	</span>rear = head;
		}
		return temp.data;
	}
	
	public T find(T t) {
		if (isEmpty()) {
			return null;
		}
		Link<T> find = head;
		while (find != null) {
			if (!find.data.equals(t)) {
				find = find.next;
			} else {
				break;
			}
		}
		if (find == null) {
			return null;
		}
		return find.data;
 	}
	
	public T delete(T t) {
		if (isEmpty()) {
			return null;
		} else {
			if (head.data.equals(t)) {
				Link<T> temp = head;
				head = head.next; //变更首结点,为下一结点
				return temp.data;
			}
		}
		Link<T> p = head;
		Link<T> q = head;
		while (!p.data.equals(t)) {
			if (p.next == null) {//表示到链尾还没找到
				return null;
			} else {
				q = p;
				p = p.next;
			}
		}
		q.next = p.next;
		return p.data;
	}
	
	public void displayList() {//遍历
		System.out.println("List (head-->last):");
		Link<T> current = head;
		while (current != null) {
			current.displayLink();
			current = current.next;
		}
	}
	
	public void displayListReverse() {//反序遍历
		if (isEmpty()) {
			return;
		}
		Link<T> p = head, q = head.next, t;
		while (q != null) {//指针反向,遍历的数据顺序向后
			t = q.next; //no3
			if (p == head) {// 当为原来的头时,头的.next应该置空
				p.next = null;
			}
			q.next = p;// no3 -> no1  pointer reverse
			p = q; //start is reverse
			q = t; //no3 start
		}
		//上面循环中的if里,把head.next 置空了, 而当q为null不执行循环时,p就为原来的最且一个数据项,反转后把p赋给head
		head = p; 
		displayList();
	}
	
	class Link<T> {//链结点
		T data;		//数据域
		Link<T> next; //后继指针,结点		链域
		Link(T data) {
			this.data = data;
		}
		void displayLink() {
			System.out.println("the data is " + data.toString());
		}
	}
	
	public static void main(String[] args) {
		TwoEndpointList<Integer> list = new TwoEndpointList<Integer>();
		list.insertLast(1);
		list.insertFirst(2);
		list.insertLast(3);
		list.insertFirst(4);
		list.insertLast(5);
		list.displayList();
		
		list.deleteHead();
		list.displayList();
		
		System.out.println("find:" + list.find(6));
		System.out.println("find:" + list.find(3));

		System.out.println("delete find:" + list.delete(6));
		System.out.println("delete find:" + list.delete(5));
		list.displayList();
		System.out.println("----reverse----");
		list.displayListReverse();
	}
}
打印

List (head-->last):
the data is 4
the data is 2
the data is 1
the data is 3
the data is 5
List (head-->last):
the data is 2
the data is 1
the data is 3
the data is 5
find:null
find:3
delete find:null
delete find:5
List (head-->last):
the data is 2
the data is 1
the data is 3
----reverse----
List (head-->last):
the data is 3
the data is 1
the data is 2
/**
 * 使用链表实现栈  ,用前插 单链表就能实现,
 * 本类采用双端链表实现
 * @author stone
 *
 */
public class LinkStack<T> {
	private TwoEndpointList<T> datas;
	
	public LinkStack() {
		datas = new TwoEndpointList<T>();
	}
	
	// 入栈
	public void push(T data) {
		datas.insertFirst(data);
	}
	
	// 出栈
	public T pop() {
		return datas.deleteHead();
	}
	
	// 查看栈顶
	public T peek() {
		return datas.peekHead();
	}
	
	//栈是否为空
	public boolean isEmpty() {
		return datas.isEmpty();
	}
	
	public static void main(String[] args) {
		LinkStack<Integer> stack = new LinkStack<Integer>();
		for (int i = 0; i < 5; i++) {
			stack.push(i);
		}
		for (int i = 0; i < 5; i++) {
			Integer peek = stack.peek();
			System.out.println("peek:" + peek);
		}
		for (int i = 0; i < 6; i++) {
			Integer pop = stack.pop();
			System.out.println("pop:" + pop);
		}
		
		System.out.println("----");
		for (int i = 5; i > 0; i--) {
			stack.push(i);
		}
		for (int i = 5; i > 0; i--) {
			Integer peek = stack.peek();
			System.out.println("peek:" + peek);
		}
		for (int i = 5; i > 0; i--) {
			Integer pop = stack.pop();
			System.out.println("pop:" + pop);
		}
	}
}
打印

peek:4
peek:4
peek:4
peek:4
peek:4
pop:4
pop:3
pop:2
pop:1
pop:0
pop:null
----
peek:1
peek:1
peek:1
peek:1
peek:1
pop:1
pop:2
pop:3
pop:4
pop:5
/**
 * 链表实现 队列  用双端链表实现
 * @author stone
 *
 */
public class LinkQueue<T> {
	private TwoEndpointList<T> list;
	
	public LinkQueue() {
		list = new TwoEndpointList<T>();
	}
	//插入队尾
	public void insert(T data) {
		list.insertLast(data);
	}
	//移除队头
	public T remove() {
		return list.deleteHead();
	}
	//查看队头
	public T peek() {
		return list.peekHead();
	}
	
	public boolean isEmpty() {
		return list.isEmpty();
	}
	
	public static void main(String[] args) {
		LinkQueue<Integer> queue = new LinkQueue<Integer>();
		for (int i = 1; i < 5; i++) {
			queue.insert(i);
		}
		for (int i = 1; i < 5; i++) {
			Integer peek = queue.peek();
			System.out.println("peek:" + peek);
		}
		for (int i = 1; i < 5; i++) {
			Integer remove = queue.remove();
			System.out.println("remove:" + remove);
		}
		
		System.out.println("----");
		
		for (int i = 5; i > 0; i--) {
			queue.insert(i);
		}
		for (int i = 5; i > 0; i--) {
			Integer peek = queue.peek();
			System.out.println("peek2:" + peek);
		}
		for (int i = 5; i > 0; i--) {
			Integer remove = queue.remove();
			System.out.println("remove:" + remove);
		}
	}
}
打印

peek:1
peek:1
peek:1
peek:1
remove:1
remove:2
remove:3
remove:4
----
peek2:5
peek2:5
peek2:5
peek2:5
peek2:5
remove:5
remove:4
remove:3
remove:2
remove:1

/* * 基于双向链表实现双端队列结构 */ package dsa; public class Deque_DLNode implements Deque { protected DLNode header;//指向头节点(哨兵) protected DLNode trailer;//指向尾节点(哨兵) protected int size;//队列中元素的数目 //构造函数 public Deque_DLNode() { header = new DLNode(); trailer = new DLNode(); header.setNext(trailer); trailer.setPrev(header); size = 0; } //返回队列中元素数目 public int getSize() { return size; } //判断队列是否为空 public boolean isEmpty() { return (0 == size) ? true : false; } //取首元素(但不删除) public Object first() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return header.getNext().getElem(); } //取末元素(但不删除) public Object last() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return trailer.getPrev().getElem(); } //在队列前端插入新节点 public void insertFirst(Object obj) { DLNode second = header.getNext(); DLNode first = new DLNode(obj, header, second); second.setPrev(first); header.setNext(first); size++; } //在队列后端插入新节点 public void insertLast(Object obj) { DLNode second = trailer.getPrev(); DLNode first = new DLNode(obj, second, trailer); second.setNext(first); trailer.setPrev(first); size++; } //删除首节点 public Object removeFirst() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = header.getNext(); DLNode second = first.getNext(); Object obj = first.getElem(); header.setNext(second); second.setPrev(header); size--; return(obj); } //删除末节点 public Object removeLast() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = trailer.getPrev(); DLNode second = first.getPrev(); Object obj = first.getElem(); trailer.setPrev(second); second.setNext(trailer); size--; return(obj); } //遍历 public void Traversal() { DLNode p = header.getNext(); while (p != trailer) { System.out.print(p.getElem()+" "); p = p.getNex
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值