最近想回顾一下数据结构,然后了解学习一些更高级的数据结构,这样在学习算法的时候应该更容易一些。所以打算重新简单实现一下常见的数据结构。在这篇文章中,我根据链表的定义简单实现了单链表的结构,编程语言选择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;
}
}
总结:
- 整体来讲,单链表算是比较简单的数据结构了,实现起来也不是非常复杂。
- 上面的链表中还可以维护一个尾指针,这样可以降低尾插和删除尾结点的时间复杂度。
应该还有很多能优化的地方,希望大佬们如果有自己的见解可以在评论区发表自己的思路。