目录
- 链表的概念及结构
- 单向链表
- 创建节点类
- 定义头节点
- 插入
- 头插法
- 尾插法
- 任意位置插入
- 查找n位置节点
- 删除节点
- 其它方法
- 判空
- 计算链表长度
- 打印链表
- 完整代码
- 双向链表
- 创建类
- 头节点与尾节点
- 头插法
- 尾插法
- 任意位置插入
- 删除出现的值
- 完整代码及运行结果
链表的概念及结构
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
就拿带头单向非循环链表来讲。
val就是数值,可以随便给。
next连接下一个地址,这样就可以串联起来了。
地址可以是无序的,不像顺序表一样它的地址必须是有序的。
单向链表
创建节点类
class ListNode{
public int val;
public ListNode next;
//构造方法只需要传val值就可以了。
public ListNode(int val) {
this.val = val;
}
}
定义头节点
public ListNode head;
插入
头插法
public void headInsert(int val) {
//首先new一个节点
ListNode node = new ListNode(val);
//判断链表是否为空
if(empty()) {
this.head = node;
} else {
node.next = this.head;
this.head = node;
}
}
尾插法
尾插法:如果链表为空就让头节点指向这个new出来的节点,如果链表不为空,定义一个cur,在cur.next不为空的情况下,让cur = cur.next,走到最后一个节点,让最后一节点的next指向node。
public void tailInsert(int val) {
ListNode node = new ListNode(val);
if(empty()) {
this.head = node;
} else {
ListNode cur = this.head;
while(cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
}
任意位置插入
public void insert(int val,int n) {
ListNode node = new ListNode(val);
if(empty()) {
this.head = node;
}
if(n == 0) {
//使用头插法
headInsert(val);
return;
}
if(n == size()) {
//使用尾插法
tailInsert(val);
return;
}
ListNode cur = this.head;
int count = 1; //计数,与n相等时插入,默认下标从1开始
while(n - 1 != count) {
count++;
cur = cur.next;
}
node.next = cur.next;
cur.next = node;
}
查找n位置节点
public ListNode findN(int n) {
if(this.head == null) return null;
if(n < 0 || n > size()) return null;
ListNode cur = this.head;
int count = 0;
while(cur != null) {
count++;
if(count == n) return cur;
cur = cur.next;
}
return null;
}
删除节点
public void delVal (int val) {
//判空
if(empty()) return;
if(this.head.val == val) {
this.head = this.head.next;
return;
}
ListNode prev = this.head;
ListNode cur = prev.next;
while(cur != null) {
if(cur.val == val) {
prev.next = cur.next;
} else {
prev = cur;
}
cur = cur.next;
}
}
其它方法
判空
public boolean empty() {
return this.head == null;
}
计算链表长度
public int size() {
int count = 0;
ListNode cur = this.head;
while(cur != null) {
count++;
cur = cur.next;
}
return count;
}
打印链表
public void display() {
ListNode cur = this.head;
while(cur != null) {
System.out.println(cur.val);
cur = cur.next;
}
}
完整代码
class ListNode{
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
public class LinkedList {
public ListNode head;
//判断是否为空
public boolean empty() {
return this.head == null;
}
//计算链表长度
public int size() {
int count = 0;
ListNode cur = this.head;
while(cur != null) {
count++;
cur = cur.next;
}
return count;
}
//打印链表
public void display() {
ListNode cur = this.head;
while(cur != null) {
System.out.println(cur.val);
cur = cur.next;
}
}
//头插法
public void headInsert(int val) {
//首先new一个节点
ListNode node = new ListNode(val);
//判断链表是否为空
if(empty()) {
this.head = node;
} else {
node.next = this.head;
this.head = node;
}
}
//尾插法
public void tailInsert(int val) {
ListNode node = new ListNode(val);
if(empty()) {
this.head = node;
} else {
ListNode cur = this.head;
while(cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
}
//任意位置插入
public void insert(int val,int n) {
ListNode node = new ListNode(val);
if(empty()) {
this.head = node;
}
if(n == 0) {
//使用头插法
headInsert(val);
return;
}
if(n == size()) {
//使用尾插法
tailInsert(val);
return;
}
ListNode cur = this.head;
int count = 1; //计数,与n相等时插入,默认下标从1开始
while(n - 1 != count) {
count++;
cur = cur.next;
}
node.next = cur.next;
cur.next = node;
}
//查找n位置的节点
public ListNode findN(int n) {
if(this.head == null) return null;
if(n < 0 || n > size()) return null;
ListNode cur = this.head;
int count = 0;
while(cur != null) {
count++;
if(count == n) return cur;
cur = cur.next;
}
return null;
}
//删除节点
public void delVal (int val) {
//判空
if(empty()) return;
if(this.head.val == val) {
this.head = this.head.next;
return;
}
ListNode prev = this.head;
ListNode cur = prev.next;
while(cur != null) {
if(cur.val == val) {
prev.next = cur.next;
} else {
prev = cur;
}
cur = cur.next;
}
}
public static void main(String[] args) {
LinkedList myList = new LinkedList();
myList.headInsert(2);
myList.headInsert(1);
myList.tailInsert(3);
myList.insert(0,0);
myList.insert(5,3);
System.out.println(myList.size());
System.out.println(myList.findN(3).val);
myList.delVal(0);
myList.display();
}
}
双向链表
如果掌握了单向链表,那么双向链表会更加的简单。
注意:增加或者删除一个节点,那么它的next与prev都要改动。
创建类
class ListDNode{
public int val;
public ListDNode next; //后继
public ListDNode prev;//前驱
public ListDNode(int val) {
this.val = val;
}
}
头节点与尾节点
public ListDNode head;
public ListDNode last;
头插法
public void headInsert(int val) {
ListDNode node = new ListDNode(val);
if(isEmpty()) {
this.head = node;
this.last = node;
} else {
node.next = this.head;
this.head.prev = node;
this.head = node;
}
}
尾插法
public void tailInsert(int val) {
ListDNode node = new ListDNode(val);
if(isEmpty()) {
this.head = node;
this.last = node;
} else {
this.last.next = node;
node.prev = this.last;
this.last = node;
}
}
任意位置插入
public void insert(int val,int n) {
if(n > size() || n < 0) return;
if(n == 0) {
headInsert(val);
return;
}
if(n == size()) {
tailInsert(val);
return;
}
ListDNode node = new ListDNode(val);
ListDNode cur = this.head;
while(n != 0) {
cur = cur.next;
n--;
}
node.next = cur;
node.prev = cur.prev;
cur.prev.next = node;
cur.prev = node;
}
删除出现的值
public void delAll(int val) {
ListDNode cur = this.head;
while(cur != null) {
if(cur.val == val) {
if(cur.val == this.head.val) {
this.head = this.head.next;
this.head.prev = null;
} else {
cur.prev.next = cur.next;
if(cur.next != null) {
cur.next.prev = cur.prev;
} else {
this.last = this.last.prev;
}
}
}
cur = cur.next;
}
}
完整代码及运行结果
class ListDNode{
public int val;
public ListDNode next;
public ListDNode prev;
public ListDNode(int val) {
this.val = val;
}
}
public class DoubleLinkedList {
public ListDNode head;
public ListDNode last;
public boolean isEmpty() {
return this.head == null;
}
public void display() {
ListDNode cur = this.head;
while(cur != null) {
System.out.print(cur.val + " ");
cur = cur.next;
}
}
public int size() {
ListDNode cur = this.head;
int count = 0;
while(cur != null) {
count++;
cur = cur.next;
}
return count;
}
//头插法
public void headInsert(int val) {
ListDNode node = new ListDNode(val);
if(isEmpty()) {
this.head = node;
this.last = node;
} else {
node.next = this.head;
this.head.prev = node;
this.head = node;
}
}
//尾插法
public void tailInsert(int val) {
ListDNode node = new ListDNode(val);
if(isEmpty()) {
this.head = node;
this.last = node;
} else {
this.last.next = node;
node.prev = this.last;
this.last = node;
}
}
//任意位置插入
public void insert(int val,int n) {
if(n > size() || n < 0) return;
if(n == 0) {
headInsert(val);
return;
}
if(n == size()) {
tailInsert(val);
return;
}
ListDNode node = new ListDNode(val);
ListDNode cur = this.head;
while(n != 0) {
cur = cur.next;
n--;
}
node.next = cur;
node.prev = cur.prev;
cur.prev.next = node;
cur.prev = node;
}
//删除出现一次的值
public void deleteNode(int val) {
if(isEmpty()) return;
if(this.head.val == val) {
this.head = this.head.next;
this.head.prev = null;
return;
}
if(this.last.val == val) {
this.last.prev.next = null;
this.last = this.last.prev;
return;
}
ListDNode cur = this.head;
while(cur != null) {
if(cur.val == val) {
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
return;
}
cur = cur.next;
}
}
//删除所有出现的值
public void delAll(int val) {
ListDNode cur = this.head;
while(cur != null) {
if(cur.val == val) {
if(cur.val == this.head.val) {
this.head = this.head.next;
this.head.prev = null;
} else {
cur.prev.next = cur.next;
if(cur.next != null) {
cur.next.prev = cur.prev;
} else {
this.last = this.last.prev;
}
}
}
cur = cur.next;
}
}
public static void main(String[] args) {
DoubleLinkedList myList = new DoubleLinkedList();
myList.headInsert(1);
myList.headInsert(2);
myList.tailInsert(3);
myList.tailInsert(5);
myList.insert(4,4);
myList.insert(22,3);
myList.insert(11,1);
myList.delAll(11);
myList.display();
}
}