顺序表的问题及思考:
思考: 如何解决以上问题呢?下面给出了链表的结构来看看
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的
//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 一个节点的时候就是创建一个节点,值为 1ListNode 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 一个节点的时候就是创建一个节点,值为 1ListNode 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;}};