单链表及其结点
- 链表是一系列的存储数据元素的单元通过指针串接起来形成的,因此每个单元至少有两个域。一个域用于数据元素的存储,另一个域是指向其他单元的指针。这里具有一个数据域和多个指针域的存储单元通常称为结点。
- 一种最简单的结点结构如图所示,它是构成单链表的基本结点结构。在结点中数据域用来存储数据单元,指针域用于指向下一个具有相同结构的结点。因为只有一个指针结点,称为单链表
- 单链表的一个重要特性就是只能通过前驱结点找到后续结点,而无法从后继结点找到前驱结点
- 查询操作
在单链表中进行查找操作,只能从链表的首结点开始,通过每个结点的next引用来依次访问链表中的每个结点以完成相应的查找操作。
例如,需要在单链表中查找是否包含某个数据元素e,则方法是使用一个循环变量p,起始时从单链表的头结点开始,每次循环判断p所指结点的数据域是否和e相同,如果相同则可以返回true,否则让p指向下一个结点,继续循环直到链表中多有结点均被访问,此时p为null
- 添加操作
在单链表中数据元素的插入,是通过在链表中插入数据元素所属的结点来完成的。对于链表的不同位置,插入的过程会有细微的差别。中间、末尾的添加过程是一样的,关键是在首部添加,会有不同,会改变整个单链表的起始结点。
- 删除操作:类似添加操作
- 在使用单链表实现线性表的时候,为了使程序更加简洁,我们通常在单链表的最前面添加一个哑元结点,也称为头结点。在头结点中不存储任何实质的数据对象,其next域指向线性表中0号元素所在的结点。可以对空表、非空表的情况以及对首元结点进行统一处理,编程更方便,常用头结点。
- 一个带头结点的单链表实现线性表的结构图如图所示:
/**
*单链表的结点
*/
public class Node{
//private Object data; //要存储的数据
// private Node next;
Object data;
Node next;
public Node(){
}
public Node(Object data){
super();
this.data = data;
}
public Node(Object data, Node next){
super();
this.data = data;
this.next = next;
}
public Object getData(){
return data;
}
public void setData(Object data){
this.data = data;
}
public Object getNext(){
return next;
}
public void setNext(Object next){
this.next = next;
}
}
public class SingleLinkedList implements List{
private Node head = new Node(); //头结点,不存储数据,为了编程方便
private int size; //一共有几个结点
private int size(){
return size;
}
private boolean isEmpty(){
return size==0;
}
private Object get(int i){
//和顺序表不一样,不能通过索引直接计算定位,而需要从头结点开始进行查找
}
public void add(int i, Object e){
//如果i位置错误报异常
if(i<0||i>size){
throw new MyArrayIndexOutOfBoundsException("数组指针越界异常:"+i);
}
//找到前一个结点,从head结点开始
Node p = head;
for(int j=0;j<i;j++){
p=p.next;
}
//新创建一个结点
//Node newNode = new Node(e);
Node newNode = new Node();
newNode.data = e;
// newNode.next = null;
//指明新结点的直接后继结点
newNode.next = p.next;
//指明新结点的直接前驱结点
p.next = newNode();
size++;
}
public void add(Object e){
this.add(size,e);
}
public Object get(int i){
Node p = head;
for(int j=0;j<=i;j++){
p=p.next;
}
return p.data();
}
public String toString(){
if(size == 0){
return "[]";
}
StringBuilder builder = new StringBuilder("[");
Node p = head.next;
for(int i=0;i<size;i++){
if(i!=size-1){
builder.append(p.data+",");
}else{
builder.append(p.data);
}
//移动指针到下一个结点
p=p.next;
}
builder.append("]");
return builder.toString();
}
}