链表
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的
链表结构多样,组合起来8种
- 单向、双向
- 带头、不带头
- 循环、不循环
三种常用结构:
- 无头单向非循环链表:结构简单,一般不会单独用来存数据如哈希桶、图的邻接表等
- 带头循环单链表:结构较无头单向非循环链表简单。实际操作当中使用较少。
- 不带头双向循环链表:
在Java的集合框架库中LinkedList底层实现就是不带头双向循环链表。
结点类的定义
class Node
{
int val;
Node next;
Node(int val)
{
this.val=val;
this.next=bull;
}
public String toString()
{
return String.format("Node(%d)",val);
}
}
头插
思想:
- 如果要插入的数据没有结点先给他装入一个结点中
Node node = new Node();
node.value =0;
2.让原来的第一个结点成为新结点的下一个结点
node.next=head;
3.更新的第一个结点为新结点
head=node;
实现:
private static Node pushFront(Node head,int val)
{
Node node =new Node(val);
node.next=head;
return node;
}
尾插
思想:
1.空链表的情况:让新的结点成为第一个结点;
2.非空链表的情况
- 如果没在结点中,装到结点
- 让新结点的next=null;
Node node=new Node(val ); // 构造方法中已经让node.next=null;
- 找到倒数第一个结点,即找到node.next==null的结点
Node last=head;
while(last.next!=null)
{
last =last.next;
}
last就是最后一个结点
- 让原来的倒数第一个结点的下一个为新结点
last.next=node;
实现:
private static Node pushBack(Node head,int val )
{
Node node=new Node(val);
if(head==null)
{
return node;
}
else
{
Node last =head;
while(last.next!=null)
{
last =last.next;
}
last.next =node;
return head;
}
}
遍历链表所有结点(打印)
//方法一:
private static void PrintNode(Node head)
{
for(Node cur=head;cur!=null;cur=cur.next)
{
System.out.println(cur.val);
}
}
//方法二:
private static void PrintNode(Node head)
{
Node cur=head;
while(cur!=null)
{
System.out.println(cur.val);
cur=cur.next;
}
}
头删
public static Node popFront(Node head)
{
if(head==null)
{
System.err.println("链表为空,无法删除");
return null;
}
//原来的第一个结点会因为没有引用指向而被回收
return head.next;
}
尾删
思路:
1.只有一个结点:
head=head.next;
2 结点大于1:
- 找到倒数第二个结点
lastSecond.next.next=null
- 让倒数第二个结点的next=null;
- 原来最后一个结点因为没有引用指向而被回收;
实现:
public static Node popBack(Node head)
{
if(head==null)
{
System.err.println("空链表无法删除");
return null;
}
if(head.next==null)
{
return null;
}
else
{
Node lastsecond =head;
while(lastsecond.next.next!=null)
{
lastsecond=lastsecond.next;
}
lastsecond.next=null;
}
}
指定位置插入结点
private static void pushAfter(Node pos, int val)
{
Node node = new Node(val);
node.next = pos.next;
pos.next = node;
}
删除指定位置后的一个元素
private static void popAfter(Node pos)
{
pos.next = pos.next.next;
}
删除指定元素
private static Node removeElements(Node head, int val)
{
Node result = null;
Node last = null; // 记录目前 result 中的最后一个结点
Node cur = head;
while (cur != null)
{
if (cur.val == val)
{
cur = cur.next;
continue;
}
Node next = cur.next;
cur.next = null;
if (result == null)
{
result = cur;
}
else
{
last.next = cur;//挂链
}
last = cur;
cur = next;
}
return result;
}