单链表的储存结构:
定义: 单链表指的是每个节点只保留一个引用,该引用指向当前节点的下一个节点,没有引用指向头节点,尾节点的next引用为null。
功能梳理: 插入 、查找 、删除 。
代码的实现:
1.首先还是定义一个接口:
/**
* 线性表规范
*/
public interface Sequence {
/**
*向綫性表中添加元素
* @param data 要儲存的元素
*/
void add(Object data);
/**
*綫性表中刪除元素
* @param index 要刪除元素的下標
* @return 是否刪除成功
*/
boolean remove (int index);
/**
*在綫性表中查找指定索引的元素
* @param index 要查找的索引
* @return 是否删除成功
*/
Object get(int index);
/**
* 判断线性表中是否有指定元素
* @param data 要查找的元素内容
* @return
*/
boolean contains(Object data);
/**
* 修改线性表中指定内容
* @param index 要修改的元素下标
* @param newData 修改后的内容
* @return
*/
Object set(int index,Object newData);
/**
* 返回当前线性表中元素个数
* @return
*/
int size();
/**
* 直接清空线性表内容
*/
void clear();
/**
* 将线性表转化为数组
* @return
*/
Object[] toArray();
}
2.链表的初始化:
public class SequenceLinkedImpl implements Sequence{
//虚拟节点,不储存元素,专门作为头节点使用。
private Node dummyhead;
private int size;
// ------内部节点
privata class Node {
private Object data;
privata Node next;
Node(Object data , Node next){
this.data = data;
this.next = next;
}
Node(Object data){
this.data = data;
}
}
3.插入,删除,查找等操作的实现:
@Override
public void add(Object data) {
//尾插
addLast(data);
}
@Override
public boolean remove(int index) {
rangecheck(index);
Node pre = dummyHead;
for (int i = 0; i < index; i++) {
pre = pre.next;
}
//取得当前结点
Node cur = node(index);
pre.next = cur.next;
//清空当前结点
cur.next = cur = null;
size--;
return true;
}
@Override
public Object get(int index) {
rangecheck(index);
//取得相应的index的Node结点
Node node = node (index);
return node.next;
}
@Override
public boolean contains(Object data) {
Object[] datas = toArray();
if(data == null){
for (int i = 0; i < datas.length; i++) {
if(datas[i] == null) {
return true;
}
}
}else {
for (int i = 0; i < datas.length; i++) {
if(datas.equals(datas[i])){
return true;
}
}
}
return false;
}
@Override
public Object set(int index, Object newData) {
rangecheck(index);
//取得index相应的node结点;
Node node = node(index);
Object oldData = node.data;
node.data = newData;
return oldData;
}
@Override
public int size() {
return this.size;
}
@Override
public void clear() {
for(Node temp = dummyHead.next;temp != null;){
temp.data = null;
Node node = temp.next;
temp.next = null;
temp = node;
size--;
}
}
@Override
public Object[] toArray() {
Object[] results = new Object[size];//创建一个长度为size的数组;
int i = 0;
for (Node temp = dummyHead.next;temp != null;temp = temp.next){
results[i++] = temp.data;
}
return results;
}
//在指定结点位置插入新结点;
public void add(int index,Object data){
Node pre = dummyHead;
for (int i = 0; i <index ; i++) {
pre = pre.next;
}
pre.next = new Node(data,pre.next);
size++;
}
//头插
private void addFirst(Object data){
add (0,data);
}
//尾插
private void addLast(Object data){
add(size,data);
}
//检测索引是否合法
private void rangecheck(int index){
if(index < 0 || index > size){
throw new IndexOutOfBoundsException("索引非法,请重新输入");
}
}
//取得指定索引结点:
private Node node (int index){
rangecheck(index);
Node temp = dummyHead.next;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp;
}
}
对于单链表而言,功能和前面的顺序表功能基本相同,只是底层代码的一些不同而已,两者就是性能上有一些差异。
单链表的分析:
优点: 1.长度不固定两可以随意增删;2.储存空间不需要连续;3. 指定数据元素之前之后插入和删除元素不需要移动其他元素。
缺点: 不支持随机查找。
在链表中还存在一种循环链表 --- 约瑟夫环。
特点是 :尾节点不指向null,而指向头节点。这样就可以方便找打头节点。