在顺序表中,每个元素在内存中都是紧密排在一起的
为了解决上述顺序表的不足,链表牺牲了下标访问的速率,做出一下改变
public class MyLinkedList {
private int size;
Node head;
@Override
public String toString() {
return "MyLinkedList{" +
" " + size +
", " + head +
'}';
}
public MyLinkedList(MyLinkedList myLinkedList) {
}
public MyLinkedList(int date) {
}
public MyLinkedList() {
}
public class Node {
}
public void addFirst(int data) {
}
public void display() {
}
public void display(Node head) {
}
public void addLast(int data) {
}
public void addIndex(int index,int data) {
}
private void checkIndex(int index, String str) {
}
public Node getNode(int index) {
}
private Node searchPreviousOne(int index) {
}
private Node searchPreviousOne(Integer val) {
}
public boolean contains(int key) {
}
public void remove(int key) {
}
public void removeAllKey(int key) {
}
public int size() {
}
public void clear() {
}
}
节点类型(静态内部类)
public static class Node {
private int value;
Node next;
@Override
public String toString() {
return "{" +
" " + value +
", " + next +
'}';
}
public Node(int value) {
this.value = value;
}
}
下标非法对应的异常
public class IndexOutOfException extends RuntimeException{
public IndexOutOfException() {
}
public IndexOutOfException(String message) {
super(message);
}
}
private int size;
Node head;
public MyLinkedList(int date) {
this.head = new Node(date);
}
public MyLinkedList() {
}
public void addFirst(int data) {
Node first = new Node(data);
first.next = head;
head = first;
size++;
}
public void addLast(int data) {
if(head == null) {
head = new Node(data);
size++;
return;
}
Node cur = head;
while(cur.next != null) {
cur = cur.next;
}
cur.next = new Node(data);
size++;
}
由于head可能为null,而这是有影响的,所以要分情况处理
head为null,实例化一个新节点,这个新节点成为head
head不为null, 定义一个临时的引用代替head(防止链表被回收)==》cur,
【current—电流—链式访问】
到达最后一个节点,而不是cur为空
cur的后继链接新实例化的新节点
public void addIndex(int index,int data) {
//下标判断
try {
checkIndex(index, "Exception from addIndex(...)");
} catch (IndexOutOfException e) {//catch后jvm解决不了
e.printStackTrace();
return;
}
Node cur = head;
Node newOne = new Node(data);
if(index == 0) {
addFirst(data);
return;
}
//到达index的前一个节点
while(--index != 0) {
cur = cur.next;
}
newOne.next = cur.next;
cur.next = newOne;
size++;
}
private void checkIndex(int index, String str) {
if(index < 0 || index > size) {
throw new IndexOutOfException(str);
}
}
checkIndex()
去检测下标是否合理public void display() {
Node cur = head;
System.out.print("[ ");
while(cur != null) {
System.out.print(cur.value + " ");
cur = cur.next;
}System.out.println("]");
}
public void display(Node head) {
Node cur = head;
System.out.print("[ ");
while(cur != null) {
System.out.print(cur.value + " ");
cur = cur.next;
}System.out.println("]");
}
public Node getNode(int index) {
try {
checkIndex(index, "Exception from getNode(...)");
Node cur = head;
while(index-- != 0) {
cur = cur.next;
}
return cur;
} catch (IndexOutOfException e) {
e.printStackTrace();
return null;
}
}
private Node searchPreviousOne(int index) {
try {
checkIndex(index, "Exception from searchPreviousOne(...)");
} catch (IndexOutOfException e) {
e.printStackTrace();
return null;
}
if(index == 0) {
return null;
}
Node cur = head;
while(--index != 0) {
cur = cur.next;
}
return cur;
}
private Node searchPreviousOne(Integer val) {//区分下标用Integer,触发重载
int value = val.intValue();
if (value == head.value || head == null) {
return null;
} else {
Node cur = head;
while (cur.next != null) {
if (cur.next.value == value) {
return cur;
} else {
cur = cur.next;
}
}
}
return null;
}
//遍历链表查看是否存在键值~~~
public boolean contains(int key) {
if(head != null) {
Node cur = head;
while(cur != null) {
if(cur.value == key) {
return true;
}else {
cur = cur.next;
}
}
}
return false;
}
规定
当传入的参数是int型 =》 代表下标,找到下标前的一个节点
当传入的参数是Integer型 =》 代表值,找的第一个这个值前的一个节点~
contains()
方法则是遍历整个链表,找到了返回true,找不到返回false~
public void remove(int key) {
if(contains(key)) {
size--;
if(head.value == key) {
head = head.next;
}else {
Node prev = searchPreviousOne(Integer.valueOf(key));//传入Integer
prev.next = prev.next.next;
}
}
}
public void removeAllKey(int key) {
if(head == null) {
return;
}
Node prev = head;
Node cur = head.next;
while(cur != null) {
if(cur.value == key) {
size--;
prev.next = cur.next;
}else {
prev = cur;
}cur = cur.next;
}
if(head.value == key) {
size--;
head = head.next;
}
}
删除所有同键值节点~
重难点,细细理解~
动图演示:
public int size() {
return this.size;
}
public void clear() {
head = null;
size = 0;
}
下面我将讲解依此改进后的MyLinkedList,并不是完全模拟LinkedList的高级操作,但是有借鉴~
public class MyLinkedList{
private int size;
Node head;
Node last;
@Override
public String toString() {
return "MyLinkedList{" +
" " + size +
", " + head +
'}';
}
public MyLinkedList() {
}
public static class Node{
private int value;
Node next;
Node prev;
@Override
public String toString() {
return "{" +
" " + value +
", " + next +
'}';
}
public Node(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
}
Node head;
Node last;
不仅提供了头节点,还提供了尾节点
尾节点就相当于,逆向链表的头节点
尾节点的存在,我们尾插的时间复杂度就相当于O(1)
public static class Node{
private int value;
Node next;
Node prev;
@Override
public String toString() {
return "{" +
" " + value +
", " + next +
'}';
}
public Node(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
public void addFirst(int data) {
size++;
Node newOne = new Node(data);
if(head == null) {
last = newOne;
head = newOne;
}else {
newOne.next = head;
head.prev = newOne;
head = newOne;
}
}
public void addLast(int data) {
size++;
Node newOne = new Node(data);
if(last == null) {
head = newOne;
last = newOne;
}else {
newOne.prev = last;
last.next = newOne;
last = newOne;
}
}
public void addIndex(int index,int data) {
try {
checkIndex(index, "Exception from addIndex(...)");
} catch (IndexOutOfException e) {
e.printStackTrace();
return;
}
Node cur = head;
Node newOne = new Node(data);
if(index == 0) {
addFirst(data);
}else if(index == size) {
addLast(data);
}else {
while(index-- != 0) { // --index 是因为那个单链表找不到前一个节点
cur = cur.next;
}
newOne.next = cur;
newOne.prev = cur.prev;
cur.prev.next = newOne;
cur.prev = newOne;
size++;
}
}
动图演示:
public void remove(int key) {
Node cur = head;
while(cur != null) {
if(cur.value == key) {
if(cur == head) {
cur.next.prev = null;
head = head.next;
}else if (cur == last) {
cur.prev.next = null;
last = last.prev;
}else {
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
}
size--;
return;
}
cur = cur.next;
}
}
public void removeAllKey(int key) {
Node cur = head;
while(cur != null) {
if(cur.value == key) {
if(cur == head) {
cur.next.prev = null;
head = head.next;
}else if (cur == last) {
cur.prev.next = null;
last = last.prev;
}else {
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
}
size--;
}
cur = cur.next;
}
}
public void clear() {
size = 0;
while(head != null) {
head = head.next;
if(head == null) {
last = null;
return;
}
head.prev = null;
}
}
这里不带大家演示LinkedList的使用了
public static void main(String[] args) {
MyLinkedList myLinkedList = new MyLinkedList();
System.out.println(myLinkedList.size());
myLinkedList.addLast(155);
System.out.println(myLinkedList.size());
myLinkedList.addLast(15);
System.out.println(myLinkedList.size());
myLinkedList.addFirst(166);
System.out.println(myLinkedList.size());
myLinkedList.addFirst(16);
System.out.println(myLinkedList.size());
myLinkedList.addIndex(0, 6);
System.out.println(myLinkedList.size());
myLinkedList.addIndex(5, 5);
myLinkedList.addIndex(1, 7);
myLinkedList.display();
System.out.println("=================");
myLinkedList.clear();
myLinkedList.addLast(155);
myLinkedList.addLast(15);
myLinkedList.addFirst(166);
myLinkedList.addFirst(16);
myLinkedList.addIndex(0, 6);
myLinkedList.addIndex(5, 5);
myLinkedList.addIndex(1, 7);
myLinkedList.remove(15);
myLinkedList.remove(166);
System.out.println(myLinkedList);
myLinkedList.clear();
System.out.println("================");
myLinkedList.addFirst(55);
myLinkedList.addFirst(55);
myLinkedList.addFirst(55);
myLinkedList.addIndex(2, 555);
myLinkedList.removeAllKey(55);
myLinkedList.display();
System.out.println(myLinkedList.contains(555));
System.out.println(myLinkedList.contains(55));
}
文章到此结束!谢谢观看 !
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭!本章节我们学会了单链表以及双向链表的基础使用,我将在另一篇文章中,
用学到的知识去解决一些oj难题!
这些oj题就包含你们所感兴趣的特殊链表类型~
敬请期待吧~