1.链表的简介
链表是一种物理存储结构上非连续存储结构

编辑

编辑
- data:表示链表的值(数据域)
- next: 表示存储的下一个结点的地址(指针域)
- 链表就是通过这样的链式存储方式进行连接,可以很大的节省开支,因为插入一个元素不用像顺序表那样移动多余的元素
2.建立链表
为了方便讲解,我这里按照自己的思路建立了一个链表
定义链表的节点
public class Mystringlist implements List<Void> {
/*
* 将结点LineNode定义为内部类
* 内部类 由诺干个成员构成
* Linenode 由数据域和next域构成,所以定义为内部类
* next引用的是一个结点的类型,存储的是下一个结点的地址,
* 相当于 LineNode next = new LineNode();
* public LineNode(int val) {
this.val = val;
}
* 因为不知道后面的结点,只知道当前结点的是,next的值为null
* */
static class LineNode {
public int val ;
public LineNode next;
public LineNode(int val) {
this.val = val;
}
}
public LineNode head;//头结点的标识,是属于链表的成员定义在内部类的外部
/*
* 建立链表*/
public void creatList() {
LineNode node1 =new LineNode(12);
LineNode node2 =new LineNode(22);
LineNode node3 =new LineNode(32);
LineNode node4 =new LineNode(42);
LineNode node5 =new LineNode(52);
LineNode node6 =new LineNode(444);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
this.head = node1;//让head指向第一个位置,当变量回收过后,任然可以通过head找到
//链表和各个节点的位置
}
3.头插法
顾名思义,在链表的头结点进行插入元素
编辑
- 在head头结点的前面插入node结点
- 插入过后,node结点的下一位就是原来的head结点:node.next = this.head;
- 此时node就成为了新的结点:this.head = node;
/*
* 头插法
*在头节点的前面进行插入
* node.next = this.head;
* 代表要插入的节点和原来链表的第一个节点相连接
* this.head = node;
* 表示插入的节点就是头节点
* */
public void addFirst(int data) {
LineNode node = new LineNode(data);
if (this.head == null) {
this.head = node;
}else {
node.next = this.head;
this.head = node;
}
}
4.尾插法
就是在链表的末尾进行插入结点的操作
编辑
- 首先找到链表的最后一个结点,判断的条件是cur.next == null
- 然后插入node结点:cur.next = node
/*
* 尾插法
* 实例化一个节点
* 找到链表最后一个节点,然后插入到最后
*判断的条件cur.next != null
*
* */
public void addLast(int data){
LineNode node = new LineNode(data);
LineNode cur = this.head;
if (this.head == null) {
this.head = node;
}else {
while (cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
}
5.在任意位置插入结点
编辑
- cur为此时要插入结点的位置
- 插入node结点,原来cur的下一个是3,插入过后cur的下一个结点就是4:cur.next = node;
- 所以node下一位就是3(原来cur的下一个位置):node.next = cur.next;
/*
* 在任意位置插入节点
* int indx 插入节点的位置
* */
public void addIndex(int indx,int data) {
if (indx < 0 || indx > size()) {
//自定义一个异常
return;
}
if (indx == 0) {
//头插法,插入到链表的首部
addFirst(data);
return;
}
if (indx == size()) {
//插入到链表的最后一个位置,尾插法
addLast(data);
return;
}
LineNode cur = search(indx);//找到要插入节点的位置
LineNode node = new LineNode(data);//创建一个新的节点
node.next = cur.next;
cur.next = node;
}
/*
* count代表头节点的位置
* indx代表插入节点
* 当头节点不断地后移,知道到达要插入节点的前一个节点的位置
* 返回该节点的位置即可*/
private LineNode search(int indx) {
LineNode cur = this.head;
int count = 0;
while (count != indx - 1) {
cur = cur.next;
count++;
}
return cur;
}
6.删除节点
编辑
- 首先需要找到要删除节点的前驱,这样才能连接链表
- 删除del节点过后,cur的下一个结点就是3: cur.next = del.next;
/*
* 删除结点
*
* */
public void remove1(int key){
//头节点删除
if (this.head.val ==key) {
this.head = this.head.next;
return;
}
//找到要删除结点的前驱
LineNode cur = find(key);
if (cur == null) {
System.out.println("error");
return ;
}
//删除
//del是要删除的结点
LineNode del = cur.next;
cur.next = del.next;
}
//找到删除结点的前驱
private LineNode find(int key) {
LineNode cur = this.head;
while (cur.next != null) {
if (cur.next.val == key) {
return cur;
}
//不断循环下一个结点直到找到key
cur = cur.next;
}
return null;
}
ps:需要了解更多的数据结构知识点,可以留言,免费领取《大话数据结构》pdf