数据结构 -- 链式存储结构 栈、队列、循环链表的实现。

链式存储结构中栈、队列、循环链表,都是在上篇的单链表基础上进行实现的。话不多说先看链式存储的栈。

先看一下的类图:
在这里插入图片描述
接下来是实现:

public class LinkedStack<E> implements Stack<E>{
 
	private LinkedList<E>  list; //创建链表的引用
	
	public LinkedStack() {
		list = new LinkedList<E>(); //创建一个链表的对象
	}
	@Override
	public int getSize() { //获取栈的容量
		return list.getSize(); //调用链表的getSize方法获取链表的有效元素
	}
 
	@Override
	public boolean isEmpty() { //判空
		return list.isEmpty(); //那就判断此时链表是否为空
	}
 
	@Override
	public void push(E e) { //进栈
		list.addFirst(e); //进栈元素总是在前一个进栈元素的前面或者上面,因此采用头插法
                                 //调用链表的在头添加结点的方法
	}
 
	@Override
	public E pop() { //出栈
		return list.removeFirst(); //将最上面的元素删除
	}
 
	@Override
	public E peek() { //获取栈顶元素
		return list.getFirst(); //获取链表的头结点的数据
	}
 
	@Override
	public void clear() { //清空
		list.clear(); //清空当前的链表
	}
 
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("LinkedStack:size="+this.getSize()+"\n");
		if(isEmpty()) {
			sb.append("[]");
		}
		else {
			sb.append('[');
			for (int i = 0; i < this.getSize(); i++) {	//O(n)
				sb.append(list.get(i));	//O(n)
				if(i!=this.getSize()-1) {
					sb.append(',');
				}
				else {
					sb.append(']');
				}
			}
		}
		return sb.toString();
	}
	@Override
	public boolean equals(Object obj) {
		if(obj==null) {
			return false;
		}
		if(obj==this) {
			return true;
		}
		if(obj instanceof LinkedStack) {
			LinkedStack ls = (LinkedStack) obj;
			if(list.equals(ls.list)) {
				return true;
			}
		}
		return false;
	}
}

然后看队列

队列

思想和顺序队列是类似的,看类图如下:
在这里插入图片描述
然后实现:

import com.openlab.队列.Queue;

public class LinkedQueue<E> implements Queue<E>{
	private LinkedList<E> list;
	public LinkedQueue() {
		list = new LinkedList<>();
	}

	@Override
	public int getSize() {
		return list.getSize();
	}

	@Override
	public boolean isEmpty() {
		return list.isEmpty();
	}

	@Override
	public void clear() {
		list.chear();
	}

	@Override
	public void enqueue(E e) {
		list.addLast(e);
	}

	@Override
	public E dequeue() {
		return list.removeFirst();
	}

	@Override
	public E getFront() {
		return list.getFirst();
	}

	@Override
	public E getRear() {
		return list.getLast();
	}
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("LinkedQueue:size="+this.getSize()+"\n");
		if(isEmpty()) {
			sb.append("[]");
		}
		else {
			sb.append('[');
			for (int i = 0; i < this.getSize(); i++) {	//O(n)
				sb.append(list.get(i));	//O(n)
				if(i!=this.getSize()-1) {
					sb.append(',');
				}
				else {
					sb.append(']');
				}
			}
		}
		return sb.toString();
	}
	@Override
	public boolean equals(Object obj) {
		if(obj == null) {
			return false;
		}
		if(obj == this) {
			return true;
		}
		if(obj instanceof LinkedQueue) {
			LinkedQueue lq = (LinkedQueue) obj;
			if(list.equals(lq.list)) {
				return true;
			}
		}
		return false;
	}
}

循环链表

在实现循环链表的结构时,采用的是真实头结点的链式结构实现的。就不能再用已经实现的链式队列去实现循环链表了,在顺序存储结构的循环队列中,我们采用的是索引下标循环的方法,而在链式存储结构中,只需要让尾的指针指向头,也就是原本的尾结点的指针域本来是不存储任何地址的,先在存储的是头结点的地址,如下图所示:
在这里插入图片描述
循环链表也是链表,实现的还是List接口,因为不能用已经实现的普通单向链表实现单向循环链表,所以在这里需要我们自己去实现,操作Node结点。插入和删除元素都和上篇中链表的插入和删除一样的方法,然后实现:

import com.openlab.线性表.List;

public class LoopSingle<E> implements List<E>{
	//定义单向链表的节点
	private class Node{
		E data;		//数据域
		Node next;	//指针域
		public Node() {
			this(null,null);
		}
		public Node(E data,Node next) {
			this.data=data;
			this.next=next;
		}
		@Override
		public String toString() {
			return data.toString();
		}
	}
	private Node head;	//指向头节点的头指针
	private Node rear;	//指向尾节点的尾指针
	private int size;	//记录元素个数
	
	public Node getHead() {
		return head;
	}
	public void setHead(Node head) {
		this.head = head;
	}
	public Node getRear() {
		return rear;
	}
	public void setRear(Node rear) {
		this.rear = rear;
	}
	public void setSize(int size) {
		this.size = size;
	}
	public LoopSingle() {
		head=null;
		rear=null;
		size=0;
	}
	
	@Override
	public int getSize() {
		return size;
	}

	@Override
	public boolean isEmpty() {
		return size == 0 && head == null && rear == null;
	}

	@Override
	public void add(int index, E e) {
		if(index<0||index>size) {
			throw new IllegalArgumentException("插入角标越界");
		}
		Node n = new Node(e,null);
		if(isEmpty()) {
			head=n;
			rear=n;
			rear.next=head;
		}
		else if(index==0) {	//头插
			n.next=head;
			head=n;
			rear.next=head;
		}else if(index==size) {	//尾插
			n.next=head;
			rear.next=n;
			rear=n;
		}else {
			Node p = head;
			for (int i = 0; i < index-1; i++) {
				p=p.next;
			}
			n.next=p.next;
			p.next=n;
		}
		size++;
	}

	@Override
	public void addFirst(E e) {
		add(0, e);
	}

	@Override
	public void addLast(E e) {
		add(size-1, e);
	}

	@Override
	public E get(int index) {
		if(index<0||index>=size) {
			throw new IllegalArgumentException("获取角标越界");
		}
		if(index==0) {
			return head.data;
		}
		else if(index==size-1) {
			return rear.data;
		}
		else {
			Node p = head;
			for (int i = 0; i < index; i++) {
				p=p.next;
			}
			return p.data;
		}
	}

	@Override
	public E getFirst() {
		return get(0);
	}

	@Override
	public E getLast() {
		return get(size-1);
	}

	@Override
	public void set(int index, E e) {
		if(index<0||index>=size) {
			throw new IllegalArgumentException("更改元素角标越界");
		}
		Node p = head;
		if(index==0) {
			head.data=e;
		}else if(index==size-1) {
			rear.data=e;
		}else {
			for (int i = 0; i < index; i++) {
				p=p.next;
			}
			p.data=e;
		}
	}

	@Override
	public boolean contains(E e) {
		return find(e)!=-1;
	}

	@Override
	public int find(E e) {
		if(isEmpty()) {
			return -1;
		}
		Node p = head;
		int index=0;
		while(p.data!=e) {
			p=p.next;
			index++;
			if(p==head) {
				return -1;
			}
		}
		return index;
	}

	@Override
	public E remove(int index) {
		// TODO Auto-generated method stub
		if(index<0||index>=size) {
			throw new IllegalArgumentException("删除角标越界");
		}
		E res = null;
		if(size==1) {	//只有一个元素制空
			head=null;
			rear=null;
		}
		else if(index==0) {
			res=head.data;
			head=head.next;
			rear.next=head;
		}
		else if(index==size-1) {
			Node p = head;
			while(p.next!=rear) {
				p=p.next;
			}
			p.next=rear.next;
			rear=p;
		}else {
			Node p =head;
			for (int i = 0; i < index-1; i++) {
				p=p.next;
			}
			Node del=p.next;
			res = del.data;
			p.next=del.next;
		}
		size--;
		return res;
	}

	@Override
	public E removeFirst() {
		return remove(0);
	}

	@Override
	public E removeLast() {
		return remove(size-1);
	}

	@Override
	public void removeElement(E e) {
		remove(find(e));
	}

	@Override
	public void chear() {
		head=null;
		rear=null;
		size=0;
	}
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("LoopSingle: size="+size+"\n");
		if(isEmpty()) {
			sb.append("[]");
		}else {
			Node p = head;
			sb.append('[');
			while(true) {
				sb.append(p.data);
				if(p.next==head) {
					sb.append(']');
					break;
				}
				else {
					sb.append(',');
				}
				p=p.next;
			}
		}
		return sb.toString();
	}
	@Override
	public boolean equals(Object obj) {
		// TODO
		if(obj==null) {
			return false;
		}
		if(obj==this) {
			return true;
		}
		if(obj instanceof LoopSingle) {
			LoopSingle ls = (LoopSingle) obj;
			if(size==ls.size) {
				for (int i = 0; i < ls.size; i++) {
					if(this.get(i)==ls.get(i)) {
						
					}
					else {
						return false;
					}
				}
			}
		}
		return false;
	}
}

over。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值