单向循环链表

单向循环链表:

什么是单向循环链表?
如果把单链表的最后一个节点的指针指向链表头部,而不是指向NULL,那么就构成了一个单向循环链表,通俗讲就是把尾节点的下一跳指向头结点。
为什么要使用单向循环链表?
在单向链表中,头指针是相当重要的,因为单向链表的操作都需要头指针,所以如果头指针丢失或者破坏,那么整个链表都会遗失,并且浪费链表内存空间,因此我们引入了单向循环链表这种数据结构。
如下图所示:
在这里插入图片描述
单向循环链表我们需要注意一个问题:
在链表中我们使用的是虚拟头结点,但是在循环链表中我们在遍历的时候就会遇到麻烦,因此在单向循环链表中我们使用的是真实头结点。
具体的实现示意图如下图所示:
单向循环链表的插入:

在这里插入图片描述
单向循环链表的插入与单向链表有所不同,因为单向循环链表首尾相连,所以没有从尾部插入的问题。
(1)从链表头部插入
将新插入的节点变为链表头部,next指向原来的第一个节点,在遍历整个链表找到链表末尾(即它的next指向的是head的那个节点),将这个节点的next指向新插入的节点,最后再将链表头指针指向新节点。
(2)从链表中间插入
此时插入的过程和单向链表的一样,找到要插入位置前驱节点,将前驱节点的next指向新节点的next,再将前驱节点的next指向新插入的节点。
单向循环链表的类图如下图所示:
在这里插入图片描述
具体代码实现如下图所示:

public class LoopSingle<E> implements List<E> {
	
	private class Node {
		E data;
		Node next;
		
		public Node(E data,Node next) {
			this.data = data;
			this.next = next;
		}
	}
	
	private Node head;
	private Node rear;
	private int size;
	
	public LoopSingle() {
		head = new Node(null, null);
		rear = head;
		size = 0;
	}
	
	public Node getNode() {
		return head;
	}
	
	public LoopSingle(E[] arr) {
		// TODO Auto-generated method stub
	}

	@Override
	public int getSize() {
		return size;
	}

	@Override
	public boolean isEmpty() {
		return size==0;
	}

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

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

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

	@Override
	public E get(int index) {
		if(index<0 || index>=size) {
			throw new IllegalArgumentException("查询下标非法");
		}
		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;
		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;
		} else {
			Node p = head;
			for(int i=0;i<getSize();i++) {
				if(p.data==e) {
					return i;
				}
				p = p.next;
			}
		}
		return -1;
	}

	@Override
	public E remove(int index) {
		if(index<0 || index>=size) {
			throw new IllegalArgumentException("删除下标非法");
		}
		E e = null;
		Node n;
		if(size==1) {
			e = head.data;
			clear();
		} else if(index==0) {
			n = head;
			e = head.data;
			rear.next = head.next;
			head = head.next;
			n.next = null;
		} else if(index==size-1) {
			e = rear.data;
			n = rear;
			Node p = head;
			while(p.next!=rear) {
				p = p.next;
			}
			p.next = head;
			rear = p;
			n.next = null;
		} else {
			Node p = head;
			for(int i=0;i<index-1;i++) {
				p = p.next;
			}
			n = p.next;
			e = p.next.data;
			p.next = n.next;
			n.next = null;
		}
		size--;
		return e;
	}

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

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

	@Override
	public E removeElement(E e) {
		int i = find(e);
		if(i==-1) {
			throw new IllegalArgumentException("删除元素不存在");
		}
		return remove(i);
	}

	@Override
	public void clear() {
		head = null;
		rear = null;
		size =0;
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("LoopSingle: size="+size+"\n");
		if(size==0) {
			sb.append("[]");
		} else {
			sb.append('[');
			Node p = head;
			while(p!=rear) {
				sb.append(p.data+",");
				p = p.next;
			}
			sb.append(rear.data+"]");
		}
		return sb.toString();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public boolean equals(Object obj) {
		if(obj == null) {
			return false;
		} 
		if(obj == this) {
			return true;
		}
		if(obj instanceof LoopSingle) {
			LoopSingle<E> loop = (LoopSingle<E>) obj;
			if(getSize()==loop.getSize()) {
				Node n = head;
				Node p = loop.head;
				for(int i=0;i<getSize();i++) {
					if(n.data!=p.data) {
						return false;
					}
					n = n.next;
					p = p.next;
				}
				return true;
			}
			
		}
		return false;
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值