顺序表的问题及思考:
思考: 如何解决以上问题呢?下面给出了链表的结构来看看
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的
//NodeList 表示节点 类
class ListNode{
//值域
public int val;
//下一个节点的地址
public ListNode next;
public ListNode(int val){
this.val = val;
}
}
//ListNode 表示节点 类
class ListNode{
//值域
public int val;
//下一个节点的地址
public ListNode next;
public ListNode(int val){
this.val = val;
}
}
public class MyLinkedList {
public static void main(String[] args) {
//当new 一个节点的时候就是创建一个节点,值为 1
ListNode nodeList = new ListNode(1);
}
}
单向,带头,不循环的单链表
用过列举的方式,创建几个节点,然后将他们连接起来
//ListNode 表示节点 类
class ListNode{
//值域
public int val;
//下一个节点的地址
public ListNode next;
public ListNode(int val){
this.val = val;
}
}
public class MyLinkedList {
public ListNode head;
//创建5个节点的链表
public void creatList(){
//当new 一个节点的时候就是创建一个节点,值为 1
ListNode ListNode1 = new ListNode(10);
ListNode ListNode2 = new ListNode(20);
ListNode ListNode3 = new ListNode(30);
ListNode ListNode4 = new ListNode(40);
ListNode ListNode5 = new ListNode(50);
ListNode1.next = ListNode2;
ListNode2.next = ListNode3;
ListNode3.next = ListNode4;
ListNode4.next = ListNode5;
this.head = ListNode1;
}
}
此时就有5个节点了
首先,我要区分清楚,链表 不是顺序表,不是一块连续的空间。 链表的每个元素 是由地址来连接起来的。
也就是说 我们不能使用普通思维模式 去思考 遍历链表的数据域的值
既然 链表是靠地址联系起来的,也就是说 靠 next域中 存储的地址来联系个节点的数据,
这就是我们突破点。
利用 head 遍历每个每个节点的数据 写法 head = head.next,你可以参考上面的图,来细品。
这样我们就跳转到下一个节点,算了我还是画个图,请看下图
//打印链表的数据
public void disPlay(){
ListNode cur = this.head;
while(cur != null){
System.out.print(cur.val + " " );
cur = cur.next;
}
System.out.println();
}
测试一下:
public class TestDome {
public static void main(String[] args) {
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.creatList();
myLinkedList.disPlay();
}
}
//得到单链表的长度
public int size(){
int usedSize = 0;
ListNode cur = this.head;
while(cur != null){
cur = cur.next;
usedSize++;
}
return usedSize;
};
//头插法
public void addFirst(int data){
ListNode node = new ListNode(data);
node.next = head;
head = node;
};
//尾插法
public void addLast(int data){
ListNode node = new ListNode(data);
ListNode cur = this.head;
//判断链表是否为空
if(this.head == null){
this.head = node;
} else{
while(cur.next != null){
cur = cur.next;
}
cur.next = node;
}
};
//查找是否包含关键字key是否在单链表当中
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
ListNode cur = head;
while(cur != null){
if(cur.val == key){
return true;
}
cur = cur.next;
}
return false;
};
/任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
ListNode node = new ListNode(data);
if(index < 0 || index > size()){
System.out.println("index 位置不合法!");
return;
}
if(index == 0){
addFirst(data);
return;
}
if(index == size()){
addLast(data);
return;
}
//中间位置
ListNode cur = this.head;
while(index - 1 != 0){
cur = cur.next;
index--;
}
node.next = cur.next;
cur.next = node;
};
//删除第一次出现关键字为key的节点
public void remove(int key){
//当链表为空的时候
if(size() == 0){
System.out.println("删除失败,链表为空!");
return;
}
//当删除的是头节点的时候
if(this.head.val == key){
this.head = this.head.next;
return;
}
ListNode cur = this.head;
while(cur.next != null){
if(cur.next.val == key){
cur.next = cur.next.next;
return;
}
cur = cur.next;
}
return;
};
//删除所有值为key的节点
public void removeAllKey(int key){
if(this.head == null){
System.out.println("链表为空!");
return;
}
//cur.val 就是删除的值
ListNode prev = this.head;
ListNode cur = this.head.next;
while (cur != null){
if(cur.val == key){
prev.next = cur.next;
cur = cur.next;
}else{
prev = cur;
cur = cur.next;
}
}
//删除头结点
if(head.val == key){
this.head = head.next;
}
};
清除链表里面的数据的时候,最好是一个节点一个节点的释放(置为null)
//清除单链表
public void clear(){
//粗暴的做法
//this.head = null;
while (this.head != null){
ListNode curNext = this.head;
this.head = null;
head = curNext;
}
};