数据结构之单链表的简单实现

73 阅读3分钟

最近想回顾一下数据结构,然后了解学习一些更高级的数据结构,这样在学习算法的时候应该更容易一些。所以打算重新简单实现一下常见的数据结构。在这篇文章中,我根据链表的定义简单实现了单链表的结构,编程语言选择Java。


根据我对数据结构的理解以及一些书上的定义,我们使用数据结构的目的是简化我们的编程过程,对我们的编程需求分析之后,选择合适的数据结构,不仅可以简化我们的编程步骤,也更容易让我们理解。所以对常见的数据结构,清楚他们的优点和缺点,以及不同的应用场景是十分重要的。编程就是数据结构加算法,虽然有些程序很简单,只是用了一个变量,但是内存中存储这个变量的方式也是一种数据结构,只是比较简单。


下面是链表的实现,具体的实现思路都是很简单的,所以这里就不说了,这也不是我的写这一系列文章的初心。

/**
 * 
 * @author Eric
 *
 * @param <T>
 */
public class LinkedList<T> {
	//链表的头结点
	private Node head;
	//链表中节点的数量
	private int size;
	
	public LinkedList() {
		head = null;
		size = 0;
	}
	/**
	 * 内部类,代表链表中每一个节点
	 * @author Eric
	 *
	 */
	class Node{
		T data;
		Node next;
		Node(){}
		Node(T data, Node next){
			this.data = data;
			this.next = next;
		}
	}
	
	/**
	 * 向链表中指定位置插入节点
	 * @param index
	 * @param data
	 * @return
	 */
	public boolean add(int index, T data) {
		if(index == 0) {
			addHead(data);
		}else if(index > size){
			return false;
		}else if(index == size){
			addLast(data);
		}else {
			Node p = findNode(index-1);
			Node newNode = new Node(data, p.next);
			p.next = newNode;
			size++;
		}
		return true;
	}
	
	/**
	 * 向链表的尾部插入节点
	 * @param data
	 */
	public void addLast(T data) {
		if(isEmpty()) {
			head = new Node(data, null);
		}else {
			Node p = head;
			while(p.next != null) {
				p = p.next;
			}
			p.next = new Node(data, null);
		}
		size++;
	}
	
	/**
	 * 在链表的头部插入节点
	 * @param data
	 */
	public void addHead(T data) {
		Node newHead = new Node(data, head);
		head = newHead;
		size++;
	}
	
	/**
	 * 删除指定位置的节点
	 * @param index
	 * @return
	 */
	public boolean delete(int index) {
		if(isEmpty() || index >= size) {
			return false;
		}
		if(index == 0) {
			deleteHead();
		}else {
			Node p = findNode(index-1);
			p.next = p.next.next;
		}
		size--;
		return true;
	}
	
	/**
	 * 删除头结点
	 */
	private void deleteHead() {
		head = head.next;
	}
	
	/**
	 * 更新指定位置节点的值
	 * @param index
	 * @param data
	 */
	public void update(int index, T data) {
		Node p = findNode(index);
		p.data = data;
	}
	
	/**
	 * 找到指定位置的节点
	 * @param index
	 * @return
	 */
	private Node findNode(int index) {
		int i = 0;
		Node p = head;
		while(i++ < index) {
			p = p.next;
		}
		return p;
	}
	
	/**
	 * 查询链表中是否包含某个值的节点
	 * @param data
	 * @return
	 */
	public boolean contains(T data) {
		Node p = head;
		while(p != null) {
			if(p.data.equals(data)) {
				return true;
			}
			p = p.next;
		}
		return false;
	}
	
	/**
	 * 打印链表的内容
	 */
	public void print() {
		Node p = head;
		while(p != null) {
			System.out.print(p.data + " ");
			p = p.next;
		}
	}
	/**
	 * 获取链表中节点的数量
	 * @return
	 */
	public int size() {
		return this.size;
	}
	
	/**
	 * 判断链表是否为空
	 * @return
	 */
	public boolean isEmpty() {
		return this.size == 0;
	}
}

总结:

  1. 整体来讲,单链表算是比较简单的数据结构了,实现起来也不是非常复杂。
  2. 上面的链表中还可以维护一个尾指针,这样可以降低尾插和删除尾结点的时间复杂度。

应该还有很多能优化的地方,希望大佬们如果有自己的见解可以在评论区发表自己的思路。