一、前言
之前在集合框架里面我们知道java.util包是Java的实用工具类库。在这个包中,Java提供了一些实用的方法和数据结构。例如链表LinkedList就是JAVA自己实现的一个双向链表。这篇博客就先来自己实现一个单链表。
二、单链表
关于链表可以根据三个性质来组合成不同种的链表:
1.带(不带)头结点;2.循环(非循环);3.双向(单向)链表
单链表本身是一种类型,由一个一个的节点来构成的,节点又包含data域和next域,我们自定义一个单链表就要先定义节点:data域的类型看自己放什么数据,next域则是保存下一个节点的地址,是引用类型,带头结点的头结点的data域是没有意义的
三、代码实现(增删改查)
这里我们实现的是不带头的非循环单链表
public class LinkedList {
public static class Node{
private int data;
private Node next;
public Node(int data) {
this.data = data;
}
}
private Node head;
public LinkedList() {
this.head = null;
}
//头插法 O(1)
//1.首先需要拿到一个Node;
//2.把它插入到head前面
//node.next=head;
//head=node;
public void addFirst(int data){
Node node=new Node(data);//node存储这个对象的地址
if(this.head==null){
//第一次插入节点
this.head=node;
return;
}
node.next=this.head;
this.head=node;
};
//尾插法 O(n)
public void addLast(int data){
Node node=new Node(data);
if(this.head==null){
this.head=node;
return;
}
Node cur=this.head;
while(cur.next!=null){
cur=cur.next;
}
cur.next=node;
};
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
if(index<0||index>size()){
throw new RuntimeException("index位置不合法");
}
if(index==0){
addFirst(data);
return;
}
if(index==size()){
addLast(data);
return;
}
//1,让一个引用 先走index-1步
Node prev=findIndex(index);
//
Node node=new Node(data);
node.next=prev.next;
prev.next=node;
};
//走index-1步
private Node findIndex(int index){
Node cur=this.head;
int count=0;
while(count<index-1){
cur=cur.next;
count++;
}
return cur;
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
Node cur=this.head;
while(cur!=null){
if(cur.data==key){
return true;
}
cur=cur.next;
}
return false;
};
/**
* 找到关键字key的前驱
* @param key
* @return
*/
private Node findPrev(int key){
Node prev=this.head;
while(prev.next!=null){
if(prev.next.data==key){
return prev;
}
prev=prev.next;
}
return null;
}
//删除第一次出现关键字为key的节点(删一个)
//1.找到要删除的节点的前驱 是不是头结点
//2.没有这个节点
//3.设置next的改变,达到删除的目的
public void remove(int key){
if(this.head.data==key){
this.head=this.head.next;
return;
}
Node prev=findPrev(key);
if(prev==null){
System.out.println("没有这个节点!");
return;
}
Node del=prev.next;
prev.next=del.next;
};
//删除所有值为key的节点(删很多)
public void removeAllKey(int key) {
//只需要遍历一次单链表,就把所有的key都删掉
if(this.head==null){
return;
}
Node prev = this.head;
Node cur = this.head.next;
while (cur != null) {
if(cur.data == key) {
prev.next = cur.next;
cur = cur.next;
}else{
prev = prev.next;//prev=cur;
cur = cur.next;
}
}
if(this.head.data==key){
this.head=this.head.next;
}
}
//得到单链表的长度
public int size(){
int count = 0;
Node cur = head;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
//打印单链表
public void display(){
Node cur=this.head;
while(cur!=null){
System.out.print(cur.data+" ");
cur=cur.next;
}
}
public void clear(){
this.head=null;
}
}
以上是关于单链表的一些基础增删改查操作实现,进阶的操作将会在下节保安博客中介绍~