链表是一种重要的数据结构,相比于数组,数组更像是一个顺序表,数组只要第一个元素固定,那么在他后面的元素的地址一定固定,数组在内存中是一块连续的存储区域,我们可以根据下标找到他的每个元素,这是数组和链表的一个区别
链表,见名思意,一个链子连接起来的表,元素之间的联系靠的是这个链子,这也决定了链表中的每个元素不是连续的,第一个元素在内存中的一个地方,而下一个元素可以在离他很远的地方,他们之间有一个链子连接着,这个链子准确来说是指针,第一个元素指向第二个,依次指向下去,我们对某个元素进行操作的时候,我们只能从头依次查找找到这个元素再进行操作。单链表是指单向的链表,我们只能从他的头向后查找,而双向链表,不光可以从头部向后查找,也可以从后向前查找。
数组的查找,更改方便,而数组的增加,删除方便。数组可以根据下标找到元素,而链表只能从头部依次向后查找,相比于数组的增加,删除操作会涉及到元素的移动,链表就方便很多,我们只需要把他前后的指向的元素改变一下,就可以实现元素的增加和删除。
对链表的操作也是很基本的操作,下面只是对单链表的操作
定义一个节点类,定义他的数据域,和next指针(不能说是一个指针,他是下一个元素,指针更好理解)
package demo_linkedlist;
public class Node {
public int element;
// public Node pre;
public Node next;
public Node(){
}
// public Node(int element,Node pre,Node next){
// this.element=element;
// this.pre=pre;
// this.next=next;
// }
public Node(int element,Node next){
this.element=element;
this.next=next;
}
@Override
public String toString() {
return element + "->"+next;
}
}
在定义节点的时候,定义了一个head头节点,头节点始终指向链表中的第一个元素。这样对链表中的第一个数据进行操作的时候,可以方便些
一个节点的初始化方法,为什么倒过来定义,因为在定义指向下一个元素的next指针的时候是先定义前一个元素的next指向,然而后一个节点还没有定义,倒过来就解决了。
private Node n10 = null;
private Node n8 = null;
private Node n7 = null;
private Node n6 = null;
private Node n5 = null;
private Node n4 = null;
private Node n3 = null;
private Node n2 = null;
private Node n1 = null;
private Node head = null;
public void init() {
n10 = new Node(10, null);
n8 = new Node(8, n10);
n7 = new Node(7, n8);
n6 = new Node(6, n7);
n5 = new Node(5, n6);
n4 = new Node(4, n5);
n3 = new Node(3, n4);
n2 = new Node(2, n3);
n1 = new Node(1, n2);
head = new Node(0, n1);
}
遍历节点方法
/**
* 打印每个节点的值
*/
public void print() {
Node star = head;
while (star != null) {
System.out.print(star.element + " ");
star = star.next;
}
System.out.println();
}
查找结点值为a的某个节点
/**
* 查找结点的值
*/
public Node find(int a) {
Node current = n1;
while (current.element != a) {
if (current.next == null) {
return null;
}
current = current.next;
}
return current;
}
插入节点,这时候头节点head的作用就用上了,当插入节点值小于链表中的任何元素的时候,为了保证链表的有序,只需要改变头节点的指向就可以
/**
* 插入一个节点,并保证链表依然有序
*/
public Node insert(int a) {
Node n9 = new Node(a, null);
Node current = head;
while (current.next != null) {
if (a < current.element) {
n9.next = current;
current.next = n9;
break;
}
if (current.element <= a && current.next.element > a) {
n9.next = current.next;
current.next = n9;
break;
}
current = current.next;
}
if (current.element < a && current.next == null) {
n9.next = null;
current.next = n9;
}
return current;
}
删除某个节点的方法,由于单链表的特点,我们只能从前向后查找,这样当我们找到要删除的节点的时候,由于前一个节点已经过去了,所以我们只能获得后一个节点,改变不了前一个节点的指向,解决的办法就是只需要定义两个节点,一个指向前一个,另一个指向后一个,每次遍历的时候这两个节点依次向后移动,当找到要操作的节点的时候,由于我们已经记录了前一个节点,这样只需要见到的改变一下指向即可。
/**
* 删除值为a的节点
*/
public Node delete(int a) {
Node current = head;
Node current1 = head.next;
while (current1.next != null) {
if (current1.element == a) {
current.next = current1.next;
return current;
}
current = current.next;
current1 = current1.next;
}
if (current1.next == null) {
current.next = null;
}
return current;
}
完整代码:
package demo_linkedlist;
/**
* 在链表中定义了一个head头节点,时钟在链表的头部,在执行插入操作的时候会方便些
*
*/
public class LinkedLists {
private Node n10 = null;
private Node n8 = null;
private Node n7 = null;
private Node n6 = null;
private Node n5 = null;
private Node n4 = null;
private Node n3 = null;
private Node n2 = null;
private Node n1 = null;
private Node head = null;
public void init() {
n10 = new Node(10, null);
n8 = new Node(8, n10);
n7 = new Node(7, n8);
n6 = new Node(6, n7);
n5 = new Node(5, n6);
n4 = new Node(4, n5);
n3 = new Node(3, n4);
n2 = new Node(2, n3);
n1 = new Node(1, n2);
head = new Node(0, n1);
}
public static void main(String[] args) {
LinkedLists l = new LinkedLists();
l.init();
l.print();// 遍历链表
System.out.println("查找:" + l.find(6));
l.insert(11);
System.out.println("插入数据后:" + l.head);
l.delete(11);
System.out.println("删除后:" + l.head);
}
/**
* 打印每个节点的值
*/
public void print() {
Node star = head;
while (star != null) {
System.out.print(star.element + " ");
star = star.next;
}
System.out.println();
}
/**
* 查找结点的值
*/
public Node find(int a) {
Node current = n1;
while (current.element != a) {
if (current.next == null) {
return null;
}
current = current.next;
}
return current;
}
/**
* 插入一个节点,并保证链表依然有序
*/
public Node insert(int a) {
Node n9 = new Node(a, null);
Node current = head;
while (current.next != null) {
if (a < current.element) {
n9.next = current;
current.next = n9;
break;
}
if (current.element <= a && current.next.element > a) {
n9.next = current.next;
current.next = n9;
break;
}
current = current.next;
}
if (current.element < a && current.next == null) {
n9.next = null;
current.next = n9;
}
return current;
}
/**
* 删除值为a的节点
*/
public Node delete(int a) {
Node current = head;
Node current1 = head.next;
while (current1.next != null) {
if (current1.element == a) {
current.next = current1.next;
return current;
}
current = current.next;
current1 = current1.next;
}
if (current1.next == null) {
current.next = null;
}
return current;
}
}
如有不对的地方欢迎指正!