一、单链表的基本操作:
(不带头节点的单链表)
创建一个包:把所有待实现的方法写在这个包下的一个接口中
package Test.listclass.impl;
public interface ILinked {
//头插法
void addFirst(int data);
//尾插法
void addLast(int data);
//任意位置插入,第一个数据节点为0号下标
boolean addIndex(int index,int data);
//查找是否包含关键字key是否在单链表当中
boolean contains(int key);
//删除第一次出现关键字为key的节点
int remove(int key);
//删除所有值为key的节点
void removeAllKey(int key);
//得到单链表的长度
int getLength();
void display();
void clear();
}
重新创建一个包:此包中写一个即将实现接口中的所有方法的类
package Test.listclass.dao;
import Test.listclass.impl.ILinked;
//不带头节点的单链表
public class MySingleListImpl implements ILinked {
......
}
以下的所有代码均是在MySingleListImpl类中写的:
首先在MySingleListImpl中写一个内部类Node类,该类用于在之后的各种操作中实例化一个node对象
//设置节点data域和next域
public class Node {
private int data;
public Node next;
public Node(int data) {
this.data = data;
this.next=null;
}
public int getData() {
return data;
}
public Node getNext() {
return next;
}
}
设置head为空(此处head不是头节点,它的作用是标记链表的一个节点)
private Node head;
public MySingleListImpl() {
this.head = null;
}
以下为在 MySingleListImpl类中实现接口中方法的具体代码,须将以下代码放入MySingleListImpl类中:
1.头插法:
第一次头插:直接将node赋给head;
之后插入:新的node的next指向原来的head,将新的node作为head;
@Override
public void addFirst(int data) {
Node node = new Node(data);
if (this.head == null) {
this.head = node;
} else {
node.next = head;
this.head = node;
}
}
2.尾插法:
第一次插:head直接指向node;
之后插:用cur先找到链表尾,之后直接插cur.next=node;
@Override
public void addLast(int data) {
Node node = new Node(data);
Node cur = this.head;
if (cur == null) {
this.head = node;
} else {
while (cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
}
3.在指定位置index处插入一个节点
首先找出要插入位置的前一个节点—— searchIndex(int index):
(前提:先检查此位置的合法性 ——checkIndex(int index))
找到后返回index-1处的节点
插入:需判断是否在第一个结点前插入
//找到index-1的位置
private Node searchIndex(int index) {
checkIndex(index);
if (index == 0) {
return null;
}
int count = 0;//记录走的步数
Node cur = this.head;
while (cur.next != null && count < index - 1) {
cur = cur.next;
count++;
}
return cur;
}
//检查index的合法性
private void checkIndex(int index) {
if (index < 0 || index > getLength()) {
throw new IndexOutOfBoundsException("下表不合法");
}
}
//在index位置插入data
@Override
public boolean addIndex(int index, int data) {
Node node = new Node(data);
//searchIndex:找到index前的节点,返回值赋给cur
Node cur = searchIndex(index);
//若searchIndex返回值为null,则说明index在第一个节点位置,在第一个结点this.head前插入node
if (cur == null) {
node.next = this.head;
this.head = node;
} else {
node.next = cur.next;
cur.next = node;
}
return true;
}
4.是否包含某个节点,其data值为key——遍历查找
@Override
public boolean contains(int key) {
Node cur = this.head;
while (cur != null) {
if (cur.data == key) {
return true;
}
cur = cur.next;
}
return false;
}
5.删除指定的key,若有重复,则删除第一次出现的该key
@Override
public int remove(int key) {
Node cur1 = this.head;
Node cur2 = cur1;
//用来保存将要删除节点的data
int oldData;
//要删除的节点为第一个节点
if (this.head.data == key) {
oldData = this.head.data;
cur1 = this.head.next;
this.head.next = null;
this.head = cur1;
return oldData;
}
//删除中间节点,注意循环条件,不能包括删除最后一个节点的情况
while (cur1.next != null) {
//cur2在前,cur1在后
cur2 = cur1;
cur1 = cur1.next;
if (cur1.data == key) {
oldData = cur1.data;
cur1 = cur1.next;
cur2.next = cur1;
return oldData;
}
}
//删除最后一个节点
if (cur1.data == key) {
cur2.next = null;
return cur1.data;
} else
return -1;
}
6.删除所有指定的key
public void removeAllKey(int key) {
Node pre = this.head;
Node cur = this.head.next;
while (cur != null) {
if (cur.data != key) {
pre = cur;
cur = cur.next;
} else {
pre.next = cur.next;
cur = cur.next;
}
}
if (head.data == key) {
head = head.next;
}
}
7.计算链表长度、打印链表元素、清空链表
//计算链表长度
@Override
public int getLength() {
Node cur = this.head;
int count = 0;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
@Override
public void display() {
Node cur = this.head;
while (cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
}
//清空链表
@Override
public void clear() {
while (this.head != null) {
Node cur = this.head.next;
this.head.next = null;
this.head = cur;
}
}