链表
链表的概念
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接顺序实现的,链表可以做到随用随取,在插入或删除时不用挪动元素
链表是链式存储数据的,将每一个数据元素通过结点(节点)进行存储,然后使用地址将这些节点串联起来
- 注意:
带头节点和不带头节点要注意区分一下
带头节点中链表的第一个节点是固定不变的其数值是无效的。不管数据在哪里插入和删除 , 节点的位置都不会变化
不带头节点中链表的第一个节点 (头节点) 是有效节点,数值都是有效的,如果在不带头链表中进行头插或者删除第一个节点 , 头节点会发生变化
下面重点介绍:
- 无头单向非循环链表:
结构简单,一般不会单独用来存数据 ; 实际中更多是作为其他数据结构的子结构,如 哈希桶、图的邻接表等等 - 无头双向不循环链表 :
在Java的集合框架库中LinkedList底层实现就是无头双向循环链表
链表的使用
下面的是实现单链表非循环的实现方式
功能:
- 打印链表元素
- 获取链表的长度
- 查找链表中是否包含某个元素
- 头插法(在链表最前面添加一个元素)
- 尾插法(在链表最末尾添加一个元素)
- 在链表的任意位置添加元素
- 在链表删除第一次出现指定的元素
- 删除链表中所有值为key的节点
public class MySingleList {
// 静态内部类
static class ListNode{
public int val; //存放节点数值
public ListNode next;//记录下一个节点的引用
public ListNode(int val){
this.val = val;
}
}
public ListNode head;//它是用来指向最开始的节点,先不初始化
public void createList(){
ListNode listNode1 = new ListNode(11);
ListNode listNode2 = new ListNode(21);
ListNode listNode3 = new ListNode(32);
ListNode listNode4 = new ListNode(43);
ListNode listNode5 = new ListNode(54);
listNode1.next = listNode2;
listNode2.next = listNode3;
listNode3.next = listNode4;
listNode4.next = listNode5;
// 头节点赋值给 head
this.head = listNode1;
}
// 打印
public void display(){
ListNode cur = this.head;// 把最开始的节点赋值给 cur
while (cur != null){ // cur 是判断 val 值等不等于空,不能是 cur.next 它判断地址
System.out.print(cur.val+ " ");
cur = cur.next;//cur 更新为下一个元素的地址
}
System.out.println();
}
//得到单链表的长度
public int size(){
ListNode cur = this.head;// 把最开始的节点赋值给 cur
int count = 0;
while (cur != null){ // cur 是判断 val 值等不等于空,不能是 cur.next 它判断地址
count++;
cur = cur.next;//cur 更新为下一个元素的地址
}
return count;
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
ListNode cur = this.head;
while (cur != null){
if(cur.val == key){
return true;
}
cur = cur.next;
}
return false;
}
//头插法
public void addFirst(int data){
ListNode node = new ListNode(data);//创建新的节点
node.next = head;// head 元素所指向的地址赋值给新节点
head = node; // 把 head 的指向修改为 指向 node
}
//尾插法
public void addLast(int data){
ListNode node = new ListNode(data);
ListNode cur = this.head;
if(cur == null){
this.head = node;
}else {
while (cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
if(index < 0 || index > size()){
System.out.println("index位置不合法!");
// 异常
throw new IndexWrongException("index位置不合法!");
}
if(index == 0){
// 头插法
addFirst(data);
return;
}
if(index == size()){
// 尾插法
addLast(data);
return;
}
// 先走 index-1 步,找到 cur
ListNode cur = findIndexSubOne(index);
ListNode node = new ListNode(data);
// 修改指向
node.next = cur.next;
cur.next = node;
}
private ListNode findIndexSubOne(int indext){
ListNode cur = this.head;
while (indext-1 != 0){
cur = cur.next;
indext--;
}
return cur;
}
//删除第一次出现关键字为key的节点
public void remove(int key){
// 判断当前链表是否为空
if(this.head == null){
return;
}
//判断 key 是否为头节点
if(this.head.val == key){
this.head = this.head.next;
return;
}
// 判断当前链表里是否有 key 的数值
ListNode cur = findIndexSubOne(key);
if(cur == null){
System.out.println("没有要删除的数字!");
return;
}
//删除节点
ListNode del = cur.next;
cur.next = del.next;
}
public ListNode findPrevofKey(int key){
ListNode cur = this.head;
while (cur.next != null){
if(cur.next.val == key){
return cur;
}
cur = cur.next;
}
return null;
}
//删除所有值为key的节点
public void removeAllKey(int key){
if(this.head == null){
return;
}
ListNode cur = this.head.next;
ListNode prev = this.head;
while (cur != null){
if(cur.val == key){
prev.next = cur.next;
cur = cur.next;
}else {
prev = cur;
cur = cur.next;
}
}
if(this.head.val == key){
this.head = this.head.next;
}
}
public void clear(){
this.head = null;
}
}
test
public static void main(String[] args) {
MySinleList mySinleList = new MySinleList();
//mySinleList.createList();
mySinleList.addLast(12);
mySinleList.addLast(34);
mySinleList.addLast(56);
mySinleList.addLast(78);
mySinleList.display();
System.out.println("长度:"+mySinleList.size());
System.out.println(mySinleList.contains(3));
// mySinleList.addFirst(99);
// mySinleList.display();
// mySinleList.addIndex(2,66);
// mySinleList.display();
mySinleList.remove(78);
mySinleList.display();
}
异常
public class IndexWrongException extends RuntimeException{
public IndexWrongException() {
}
public IndexWrongException(String message) {
super(message);
}
}