JAVA数据结构(三)

链表

一、线性数据结构
在这里插入图片描述

  • 链表是最简单的动态数据结构,更深入的理解引用,更深入的理解递归,辅助组成其他数据结构
    在这里插入图片描述
  • 数组和链表的对比
    在这里插入图片描述
  • 实现一个节点:
package cn.itcast.day3;

public class LinkedList<E> {
	private class Node{
		public E e;
		public  Node next;
		
		public Node(E e,Node next) {
			this.e = e;
			this.next = next;
		}
		public Node(E e) {
			this(e,null);
		}
		public Node() {
			this(null,null);
		}
		@Override
		public String toString() {
			return e.toString();
		}
	}
}

二、链表操作
对于链表来说,如果想访问存在链表中的所有节点,我们必须把链表的头(head)给存储起来。即在LinkeList中需要维护一个Node类型的head变量,他指向链表中的第一个节点。

  • 在链表头部添加元素
    在这里插入图片描述
  • 在链表中间添加元素
    在这里插入图片描述
  • 为链表设立虚拟头节点:解决头节点没有prev节点的问题
    在这里插入图片描述
  • 删除链表中的指定位置元素
    在这里插入图片描述
  • 链表的增删改查实现
package cn.itcast.day3;

public class LinkedList<E> {
	private class Node{
		public E e;
		public  Node next;
		
		public Node(E e,Node next) {
			this.e = e;
			this.next = next;
		}
		public Node(E e) {
			this(e,null);
		}
		public Node() {
			this(null,null);
		}
		@Override
		public String toString() {
			return e.toString();
		}
	}
	private Node dummyhead;
	int size;
	
	public LinkedList() {
		dummyhead = new Node(null,null);
		size = 0;
	}
	//获取链表中的元素个数
	public int getSize() {
		return size;
	}
	//返回链表是否为空
	public boolean isEmpty() {
		return size == 0;
	}
	//在指定位置添加元素
	public void add(int index,E e) {
		if(index <0 || index > size) {
			throw new IllegalArgumentException("出错");
		}
		//虚拟头节点
		Node prev = dummyhead;
		for(int i=0;i<index;i++) {
			prev = prev.next;
		}
		Node node = new Node(e);
		node.next = prev.next;
		prev.next = node;
		//prev.next = new Node(e,prev.next);三句合成一句
		size ++ ;
	}
	//在链表头添加元素
	public void addFirst(E e) {
		add(0,e);
	}
	//在链表的末尾添加新的元素e
	public void addLast(E e) {
		add(size,e);
	}
	//获得链表的第index个位置的元素
	public E get(int index) {
		if(index <0 || index > size) {
			throw new IllegalArgumentException("出错");
		}
		Node cur = dummyhead.next;
		for(int i=0;i<index;i++) {
			cur = cur.next;
		}
		return cur.e;
	}
	//获得链表的第1个位置的元素
	public E getFirst() {
		return get(0);
	}
	//获得链表的最后一个位置的元素
	public E getLast() {
		return get(size-1);
	}
	//修改链表的第index个位置的元素为e
	public void set(int index,E e) {
		if(index <0 || index > size) {
			throw new IllegalArgumentException("出错");
		}
		Node cur = dummyhead.next;
		for(int i=0;i<index;i++) {
			cur = cur.next;
		}
		cur.e = e;
	}
	//查找链表中是否有元素e
	public boolean contains(E e) {
		Node cur = dummyhead.next;
		while(cur != null) {
			if(cur.e.equals(e)) {
				return true;
			}
			cur = cur.next;
		}
		return false;
	}
	//删除指定位置的元素
	public E remove(int index) {
		if(index <0 || index > size) {
			throw new IllegalArgumentException("出错");
		}
		Node prev = dummyhead;
		for(int i=0;i<index;i++) {
			prev = prev.next;
		}
		Node delNode = prev.next;
		prev.next = delNode.next;
		delNode.next = null;
		size --;
		return delNode.e;
	}
	//删除第一个元素
	public E removeFirst() {
		return remove(0);
	}
	//删除最后一个元素
	public E removeLast() {
		return remove(size-1);
	}
	@Override
	public String toString() {
		StringBuilder res = new StringBuilder();
		Node cur = dummyhead.next;
		while(cur !=null) {
			res.append(cur+"->");
			cur = cur.next;
		}
		res.append("NULL");
		return res.toString();
	}
}

  • 测试代码
package cn.itcast.day3;

public class MAIN {

	public static void main(String[] args) {
		LinkedList<Integer> linked = new LinkedList<Integer>();
		for(int i=0;i<5;i++) {
			linked.addFirst(i);
			System.out.println(linked);
		}
		linked.add(2, 777);
		System.out.println(linked);
		linked.remove(2);
		System.out.println(linked);
	}

}

  • 链表的时间复杂度分析
    在这里插入图片描述

三、链表的应用 —> 利用链表实现栈

  • 同样利用接口
    在这里插入图片描述
  • 代码实现
package cn.itcast.day3;

public class LinkedListStack<E> implements Stack<E> {
	private LinkedList<E> list;
	
	public LinkedListStack() {
		list = new LinkedList<>();
	}
	@Override
	public int getSize() {
		return list.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 String toString() {
		StringBuilder res = new StringBuilder();
		res.append("Stack:top ");
		res.append(list);
		return res.toString();
	}

	public static void main(String[] args) {
		LinkedListStack<Integer> linked = new LinkedListStack<Integer>();
		for(int i=0;i<5;i++) {
			linked.push(i);
			System.out.println(linked);
		}
		linked.pop();
		System.out.println(linked);
	}
}
  • 利用链表实现队列
    改进链表:添加head与tail节点,记录链表的头尾节点
    在这里插入图片描述
    注意:即使现在记录了tail节点,但是直接删除tail节点也不太容易---->并不是O(1)复杂度,同样需要遍历之后才能够删除tail节点,但是在tail端添加元素容易。从head端删除节点简单。由于没有dummyHead,要注意链表为空的情况
  • 队列的代码实现
package cn.itcast.day2;

public class LinkedListQueue<E> implements Queue<E> {
	private class Node{
		public E e;
		public Node next;
		public Node(E e,Node next) {
			this.e = e;
			this.next = next;
		}
		public Node(E e) {
			this(e,null);
		}
		public Node() {
			this(null,null);
		}
		@Override
		public String toString() {
			return e.toString();
		}
	}
	private Node head,tail;
	private int size;
	public LinkedListQueue() {
		head = null;
		tail = null;
		size = 0;
	}
	@Override
	public int getSize() {
		return size;
	}
	@Override
	public boolean isEmpty() {
		return size==0;
	}
	@Override
	public void enqueue(E e) {
		if(tail == null) {
			tail = new Node(e);
			head = tail;
		}else {
			tail.next = new Node(e);
			tail = tail.next;
		}
		size++;
	}
	@Override
	public E dequeue() {
		if(isEmpty()) {
			throw new IllegalArgumentException("出错!");
		}
		Node retNode = head;
		head = head.next;
		retNode.next = null;
		if(head == null) { //如果只有一个元素,出队之后队列为空,此时需要维护tail
			tail = null;
		}
		size--;
		return retNode.e;
	}
	@Override
	public E getFront() {
		// TODO Auto-generated method stub
		if(isEmpty()) {
			throw new IllegalArgumentException("出错!");
		}
		return head.e;
	}
	@Override
	public String toString() {
		StringBuilder res = new StringBuilder();
		res.append("Queue: front ");
		Node cur = head;
		while(cur!=null) {
			res.append(cur.e+"-->");
			cur = cur.next;
		}
		res.append("-->NULL");
		return res.toString();
	}
	public static void main(String[] args) {
		LinkedListQueue<Integer> linkQueue = new LinkedListQueue<>();
		for(int i=0;i<5;i++) {
			linkQueue.enqueue(i);
			System.out.println(linkQueue);
		}
		linkQueue.dequeue();
		System.out.println(linkQueue);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值