单向链表是什么?
小时候玩过老鹰捉小鸡吧,小鸡跟着鸡妈妈, 我们让鸡妈妈抱住一棵大树,这就是虚拟向单向链表。实体的单向链表就是把树去掉吧。
大树-1>小鸡0>小鸡1>小鸡2>小鸡3>小鸡4>小鸡5>小鸡6>小鸡7。
怎么在小鸡的前面再加一只小鸡?
让大树指向新加入的小鸡,让新加入的小鸡指向小鸡0;
怎么在最末尾加一只小鸡,末尾小鸡7指向新加入小鸡8;
怎么在小鸡中加入一只小鸡?
比如在小鸡3后加入一只小鸡,让小鸡3指向新加入的小鸡,新加入的小鸡指向小鸡4 是不是就加进去了。
这么一说应该就明白了,如果不明白,那么就该放弃数据结构了。链表没有容器这个概念了。如果有,就看你的内存有多大了。
代码实现 :
单向链表实现的是List接口:
存储单元:存储的是一个个节点
节点是什么:节点是一个内部类,里面包含自身数据和一个指向。看过千手观音吧,从正面看就是一个人,里面实际有很多人,链表的存储结构就好像,是在一维里面开辟出多维。也可以这样说,你打开一个箱子,箱子里面有两部分,一部分装着数据一部分装着另一个箱子
打开箱子0里面有数据0和箱子1,打开箱子1里面有数据1和箱子2,打开箱子2 里面有数据2和箱子3 直至结束。这里实现方式是最外面的箱子永远不变,从第二层开始进行
先看接口构造:
public interface List<E> {
/*
* 获取线性表中元素的个数 线性表的长度
*@return 线性表中的有效元素的个数
*/
public int getSize();
/*
* 判断线性表是否为空
*@return 是否为空
*/
public boolean isEmpty();
public void add(int index,E e);
//表头添加元素
public void addFirst(E e);
//表尾添加元素
public void addLast(E e);
//在表中根据指定角标获取元素,指定角标大于0小于角标的个数size
public E get(int index);
//获取表头元素 返回值为表头元素 0
public E getFirst();
//获取表尾元素 返回值为表尾元素 size-1
public E getLast();
//修改线性表中指定index处的元素为E 没有返回值
public void set(int index,E e);
//判断线性表中是否包含指定元素e 参数为E 返回值为boolean
public boolean contains(E e);
//在线性表中获取元素角标 从前往后找 参数为E 返回值为int 返回数据角标
public int find(E e);
//在线性表中 根据指定角标 删除元素 并返回该元素 角标范围为:0至size-1
public E remove(int index);
//在线性表中 删除表头元素 返回表头元素
public E removeFirst();
//在线性表中 删除表尾元素 返回删除元素
public E removeLast();
//在线性表中根据元素删除指定元素
public void removeElement(E e);
//清空线性表 无返回值 无参数
public void clear();
public boolean equals(Object obj);
看单向链表实现:
1.你先得有一个箱子 这里设为私有的一个内部类,是隐藏实现细节,不让数据被外部获得。
private class Node<E>{
private E data;//存数据
prvate Node next;//存下一个箱子;这里只要记住next就行,next代表的是下一个箱子
//定义构造方法,将数据和箱子放入箱子
public Node(E data,Node next){
this.data=data;
this.next=next;
}
}
箱子已经有了,那么要对箱子进行操作了。
public clss LinkedList<E> implements List<E>{
private class Node{
//箱子放在这里,保护箱子
}
private Node<E> head; //最外层的箱子
private Node<E> rear; //最内层的箱子
private int size; //共有多少个箱子
//对管理箱子的东西进行初始化。先创建一个箱子,最外层的箱子就是这个箱子,最里层的箱子也是这个箱子
public LinkedList(){
head =new Node();
rear=head;
size=0;
//现在没有任何箱子,只有管理工具
}
public int getSize(){
//获得箱子的个数
return size;
}
/*
* 判断线性表是否为空
*@return 是否为空
*/
public boolean isEmpty(){
return rear==0&&head==0; //当管理工具中没有箱子时,那管理工具就是空的
}
//往工具里面添加箱子
public void add(int index,E e){
//对要进入哪一层进行判断
if(index<0||index>size){
throw new Exception("你选择的箱子不存在");
}
Node n=new Node(); // 创建一个新箱子
n.data=e;
if(index==0){
//往箱子里面装入这个新箱子
n.next=head.next;
head.next=n;
rear=n;
}else if(index==size){
//往最里层的箱子装东西
rear.next=n;
n.next=null;
rear=n;
}else{
//往既不是头也不是尾的地方装箱子
//这里创建一个临时箱子
Node p=new Node();
for(int i=0;i<index;i++){
//从头开始拆箱子,直到拆开第index个箱子
p=head.next;
}
//取出来第index个箱子后,让新创建的箱子n的下一个指向第index的箱子的下一个,然后让第index箱子的下一个指向n
n.next=p.next;
p.next=n;
}
size++;
}
//表头添加元素
public void addFirst(E e){
add(0);
}
//表尾添加元素
public void addLast(E e){
add(size);
}
//在表中根据指定角标获取元素,指定角标大于0小于角标的个数size
public E get(int index){
//拆箱
if(index<0||index>size){
throw new Exception("你选择的箱子不存在");
}
if(index==0){
//取第一个箱子里面的第一个箱子
return head.next.data;
}else if(index==size){
//去最后一个箱子里面的东西
return rear.data;
}else{
Node p=new Node();
for(int i=0;i<index-1;i++){
p=head.next;
}
return p.data;
}
}
//获取表头元素 返回值为表头元素 0
public E getFirst(){
get(0);
}
//获取表尾元素 返回值为表尾元素 size-1
public E getLast(){
get(size);
}
//修改线性表中指定index处的元素为E 没有返回值
public void set(int index,E e){
if(index<0||index>size){
throw new Exception("你选择的箱子不存在");
}
Node p=new Node();
for(int i=0;i<index;i++){
p=head.next;
}
p.data==e;
}
//判断线性表中是否包含指定元素e 参数为E 返回值为boolean
public boolean contains(E e){
if(find(e)!==-1)return true;
return false;
}
//在线性表中获取元素角标 从前往后找 参数为E 返回值为int 返回数据角标
public int find(E e){
for(int i=0;i<size;i++){
if(head.next.data==e) return i;
}
return -1;
}
//在线性表中 根据指定角标 删除元素 并返回该元素 角标范围为:0至size-1
public E remove(int index){
if(index<0||index>size){
throw new Exception("你选择的箱子不存在");
}
Node p1=new Node();
Node p2=new Node();
//获取index的后一个元素 与前一个元素,让前一个元素指向后一个元素
if(index==0){
p2=get(index+1);
head.next=p2;
}else if(index==size){
p1=get(index-1);
p1.next=null;
rear=p1;
}else{
p1=get(index-1);
p2=get(index+1);
p1.next=p2;
}
return get(index).data;
}
//在线性表中 删除表头元素 返回表头元素
public E removeFirst(){
remove(0);
}
//在线性表中 删除表尾元素 返回删除元素
public E removeLast(){
return remove(size);
}
//在线性表中根据元素删除指定元素
public void removeElement(E e){
remove find(e);
}
//清空线性表 无返回值 无参数
public void clear(){
head=null;
rear=null;
size=0;
}
以上均为手打,如有错误请批评指正,后期上传测试过的。