一、链表的概念
链表是是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表分为单链表、双链表、循环链表
二、链表的实现(以单链表为例)
1.单链表
1.)什么是单链表:
单向链表是一种线性表,实际上是由节点(Node)组成的,一个链表拥有不定数量的节点。其数据在内存中存储是不连续的,它存储的数据分散在内存中,每个节点只能也只有它能知道下一个节点的存储位置。由N各节点(Node)组成单向链表,每一个Node记录本Node的数据及下一个Node。向外暴露的只有一个头结点(Head),我们对链表的所有操作,都是直接或者间接地通过其头结点来进行的。
2.)单链表的图解

2.单链表的代码实现
1).单链表及结点的定义
class SingleList{
Node head;//定义一个头节点,头节点不动,不存放具体的值
private int Length;//链表的长度
public SingleList(){
head=null;
Length = 0 ;
}
//返回链表的长度
public int length(){
return this.Length;
}
//判断所需要操作位置的节点是否存在
private void outLength(int index){
if(this.Length < index || index < 0 ){ //需要操作位置大于链表长度,则抛出错误
throw new IndexOutOfBoundsException();
}
}
}
//定义一个Node,每个Node就是一个节点
class Node {
private int data;
public Node next;
public Node(int data) {
this.data = data;
}
@Override
public String toString() {
return "Node{" +
" data='" + data + '\'' +
'}';
}
}
2).链表的增删改查实现
增加节点:a.增加头节点 ;b.在指定索引处增加节点;c.在链表尾部增加节点
/**添加节点到单链表头节点
* @param node
*/
public void addHead(Node node){
//因为Head 为 null 所有直接将 head 给 node 的指向就行
node.next = this.head;
this.head = node;
this.Length++;
}
/**加入结点到指定位置
* 1.首先判断索引是否越界,越界则抛出异常
* 2.循环,到指定索引 前一个索引 所在 结点 停止
* 1.)将停止所在当前 结点 指向的 下一个结点 指向 Node 的下一个的结点
* 2.)再将当前所在的 结点 指向Node
* @param index
* @param node
*/
public void add(int index ,Node node ){
outLength(index);//需要操作位置大于链表长度,则抛出错误
if(index == 0 ){ //若要添加位置再头节点,直接调用add(方法)
addHead(node);
return;
}
Node temp = head; // 辅助链表
while (index >1 ){
temp = temp.next; //指向下一个节点
index --;
}
node.next = temp.next;//当前 节点 指向的 下一个节点 指向 Node 的下一个的节点
temp.next = node ;
this.Length++; //链表长度加1
}
/**添加节点到单链表末尾
* @param node
*/
public void addList(Node node){
add(Length,node ); //index 为链表的长度
}
删除节点:a.删除头节点;b.删除指定索引位置的节点;c.删除尾部节点
/** 删除头节点
* 并返回所删除的结点,链表长度减 1
* @return
*/
public Node removeHead(){
//判断链表是否为空
if(Length == 0){
return null ;
}
//定义一个Node 接收原先的头节点
Node node = head ;
head = head.next ; //然后删掉原头节点
node.next =null; //将原先头节点的指向改成 null
this.Length--;
return node;
}
/**删除指定位置的元素
* 并返回所删除的节点,链表长度减 1
* @param index
* @return
*/
public Node remove(int index){
outLength(index-1);//需要操作位置大于链表长度,则抛出错误
boolean flag = true;
Node temp = head; // 辅助链表
Node node = null;
while (flag){
if(index-1 < 1 ){
flag = false ;
break;
}
temp = temp.next; //指向下一个节点
index --;
}
node = temp.next; //储存要删除的节点,便于返回
temp.next = temp.next.next;
node.next = null;
this.Length--; //链表长度减1
return node;
}
/**删除链表尾部节点
* 并返回所删除的节点,链表长度减 1
* 调用remover
*/
public Node removeList(){
Node node = remove(this.Length-1);
this.Length--;
return node;
}
查询指定节点
/**查询指定节点
*
* @param index
* @return
*/
public Node showNode(int index){
outLength(index);
boolean flag = true;
Node temp = head; // 辅助链表
//将指针指向指定节点
while (flag){
if(index < 1 ){
flag = false ;
break;
}
temp = temp.next; //指向下一个节点
index --;
}
return temp;
}
/**
* 遍历链表
*/
public void showList(){
if(head == null){
System.out.println("此链表为空");
}
Node temp = head ;
while (temp != null){
System.out.println(temp);
temp=temp.next; //指向下一个节点
}
}
修改指定节点
/**修改指定结点信息
* @param index
* @return
*/
public Node upData(int index , Node upNode){
outLength(index);
boolean flag = true;
Node temp = head; // 辅助链表
Node node = null;
//将指针指向指定节点的前一位
while (index == 1 ){
temp = temp.next; //指向下一个节点
index --;
}
node = temp; // 用来储存修改前的节点
upNode.next = temp.next.next; //将修改后节点 指向 修改前 下一个节点
temp.next = upNode; //修改节点信息
node.next = null; // 将前节点的指向改为 null
return node;
}
}
3.)测试代码
public static void main(String[] args) {
SingleList sl1 = new SingleList();
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
Node n4 = new Node(4);
Node n5 = new Node(5);
//插入头节点
sl1.addHead(n1);
sl1.addHead(n2);
//打印全部节点
sl1.showList();
System.out.println("--------");
//插入头节点
sl1.addHead(n3);
//打印全部节点
sl1.showList();
System.out.println("--------");
//插入链表尾部
sl1.addList(n4);
//打印全部节点
sl1.showList();
System.out.println("--------");
//指定索引处加入节点
sl1.add(2,n5);
//打印全部节点
sl1.showList();
System.out.println("此时链表长度为:"+ sl1.length());
System.out.println("--------");
//删除头节点
sl1.removeHead();
//打印全部节点
sl1.showList();
System.out.println("--------");
//删除尾部节点
sl1.removeList();
//打印全部节点
sl1.showList();
System.out.println("--------");
//删除指定位置节点
sl1.remove(1);
//打印全部节点
sl1.showList();
System.out.println("此时链表长度为:"+ sl1.length());
System.out.println("--------");
//修改节点
sl1.upData(0,new Node (8));
//打印全部节点
sl1.showList();
System.out.println("此时链表长度为:"+ sl1.length());
System.out.println("--------");
//查询指定节点
System.out.println(sl1.showNode(0));
}
}
完整代码
public class SingleListDome {
public static void main(String[] args) {
SingleList sl1 = new SingleList();
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
Node n4 = new Node(4);
Node n5 = new Node(5);
//插入头节点
sl1.addHead(n1);
sl1.addHead(n2);
//打印全部节点
sl1.showList();
System.out.println("--------");
//插入头节点
sl1.addHead(n3);
//打印全部节点
sl1.showList();
System.out.println("--------");
//插入链表尾部
sl1.addList(n4);
//打印全部节点
sl1.showList();
System.out.println("--------");
//指定索引处加入节点
sl1.add(2,n5);
//打印全部节点
sl1.showList();
System.out.println("此时链表长度为:"+ sl1.length());
System.out.println("--------");
//删除头节点
sl1.removeHead();
//打印全部节点
sl1.showList();
System.out.println("--------");
//删除尾部节点
sl1.removeList();
//打印全部节点
sl1.showList();
System.out.println("--------");
//删除指定位置节点
sl1.remove(1);
//打印全部节点
sl1.showList();
System.out.println("此时链表长度为:"+ sl1.length());
System.out.println("--------");
//修改节点
sl1.upData(0,new Node (8));
//打印全部节点
sl1.showList();
System.out.println("此时链表长度为:"+ sl1.length());
System.out.println("--------");
//查询指定节点
System.out.println(sl1.showNode(0));
}
}
class SingleList{
Node head;//定义一个头节点,头节点不动,不存放具体的值
private int Length;//链表的长度
public SingleList(){
head=null;
Length = 0 ;
}
/** 将链表反转
*
* @param head
* @return
*/
public static Node reverseIteratively(Node head){
Node next = null;
Node temp = head; // 辅助节点
Node reverse = null;//用来储存逆转后的链表
while(temp == null){
}
return null;
}
//返回链表的长度
public int length(){
return this.Length;
}
//判断所需要操作位置的节点是否存在
private void outLength(int index){
if(this.Length < index || index < 0 ){ //需要操作位置大于链表长度,则抛出错误
throw new IndexOutOfBoundsException();
}
}
/**添加节点到单链表头节点
* @param node
*/
public void addHead(Node node){
//因为Head 为 null 所有直接将 head 给 node 的指向就行
node.next = this.head;
this.head = node;
this.Length++;
}
/**加入结点到指定位置
* 1.首先判断索引是否越界,越界则抛出异常
* 2.循环,到指定索引 前一个索引 所在 结点 停止
* 1.)将停止所在当前 结点 指向的 下一个结点 指向 Node 的下一个的结点
* 2.)再将当前所在的 结点 指向Node
* @param index
* @param node
*/
public void add(int index ,Node node ){
outLength(index);//需要操作位置大于链表长度,则抛出错误
if(index == 0 ){ //若要添加位置再头节点,直接调用add(方法)
addHead(node);
return;
}
Node temp = head; // 辅助链表
while (index >1 ){
temp = temp.next; //指向下一个节点
index --;
}
node.next = temp.next;//当前 节点 指向的 下一个节点 指向 Node 的下一个的节点
temp.next = node ;
this.Length++; //链表长度加1
}
/**添加节点到单链表末尾
* @param node
*/
public void addList(Node node){
add(Length,node ); //index 为链表的长度
}
/** 删除头节点
* 并返回所删除的结点,链表长度减 1
* @return
*/
public Node removeHead(){
//判断链表是否为空
if(Length == 0){
return null ;
}
//定义一个Node 接收原先的头节点
Node node = head ;
head = head.next ; //然后删掉原头节点
node.next =null; //将原先头节点的指向改成 null
this.Length--;
return node;
}
/**删除指定位置的元素
* 并返回所删除的节点,链表长度减 1
* @param index
* @return
*/
public Node remove(int index){
outLength(index-1);//需要操作位置大于链表长度,则抛出错误
boolean flag = true;
Node temp = head; // 辅助链表
Node node = null;
while (flag){
if(index-1 < 1 ){
flag = false ;
break;
}
temp = temp.next; //指向下一个节点
index --;
}
node = temp.next; //储存要删除的节点,便于返回
temp.next = temp.next.next;
node.next = null;
this.Length--; //链表长度减1
return node;
}
/**删除链表尾部节点
* 并返回所删除的节点,链表长度减 1
* 调用remover
*/
public Node removeList(){
Node node = remove(this.Length-1);
this.Length--;
return node;
}
/**查询指定节点
*
* @param index
* @return
*/
public Node showNode(int index){
outLength(index);
boolean flag = true;
Node temp = head; // 辅助链表
//将指针指向指定节点
while (flag){
if(index < 1 ){
flag = false ;
break;
}
temp = temp.next; //指向下一个节点
index --;
}
return temp;
}
/**
* 遍历链表
*/
public void showList(){
if(head == null){
System.out.println("此链表为空");
}
Node temp = head ;
while (temp != null){
System.out.println(temp);
temp=temp.next; //指向下一个节点
}
}
/**修改指定结点信息
* @param index
* @return
*/
public Node upData(int index , Node upNode){
outLength(index);
boolean flag = true;
Node temp = head; // 辅助链表
Node node = null;
//将指针指向指定节点的前一位
while (index == 1 ){
temp = temp.next; //指向下一个节点
index --;
}
node = temp; // 用来储存修改前的节点
upNode.next = temp.next.next; //将修改后节点 指向 修改前 下一个节点
temp.next = upNode; //修改节点信息
node.next = null; // 将前节点的指向改为 null
return node;
}
}
//定义一个Node,每个Node就是一个节点
class Node {
private int data;
public Node next;
public Node(int data) {
this.data = data;
}
@Override
public String toString() {
return "Node{" +
" data='" + data + '\'' +
'}';
}
}

被折叠的 条评论
为什么被折叠?



