存储方法
链接方式存储的线性表简称为链表(Linked List)。
链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
注意:
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。
结点结构
┌───┬───┐
│data│next│
└───┴───┘
data域–存放结点值的数据域
next域–存放结点的直接后继的地址(位置)的指针域(链域)
注意:
①链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的。
②每个结点只有一个链域的链表称为单链表(Single Linked List)。
结点定义
class ListNode{
int val;
ListNode next;
ListNode(int val){
this.val = val;
this.next = null;
}
}
常见操作
一般定义一个头结点为了方便操作,结点后面的结点是我们有效的数据
判断是否是空
public boolean isEmpty(ListNode head){
return head.next == null;
}
链表长度
public int length(ListNode head){
ListNode cur = head.next;
int len = 0;
while(cur!=null){
cur = cur.next;
len++;
}
return len;
}
输出链表
public void printList(ListNode head){
ListNode cur = head.next;
while(cur.next!=null){
System.out.print(cur.val+"-->");
cur = cur.next;
}
System.out.print(cur.val);
}
判断结点是否存在
public boolean searchNode(ListNode head ,int val){
boolean flag = false;
ListNode cur = head.next;
while(cur!=null){
if(cur.val == val){
flag = true;
break;
}
cur = cur.next;
}
return flag;
}
插入结点
第i位置插入一个新的结点
i从1开始,i表示插入到链表第i个位置
插入过程
public void insertNode(ListNode head,int i,int val){
if(i<=0)
return;
ListNode cur = head;
ListNode node = new ListNode(val);
while(i>1){
cur = cur.next;
i--;
if(cur==null){
System.out.println("插入位置大于链表长度");
return;
}
}
node.next = cur.next;
cur.next = node;
}
删除结点
删除结点重点找到其前驱结点
删除过程
public boolean deleteNode(ListNode head,int val){
boolean flag = false;
ListNode cur = head; // 头结点起到了作用
while(cur.next!=null){
if(cur.next.val == val){ // 删除 cur.next 结点
cur.next = cur.next.next;
flag = true;
break;
}
cur = cur.next;
}
return flag;
}