数据结构-链表
一、什么是链表?
链表是一种常见的数据结构,由一系列节点构成,每个节点包含当前节点的数据和一个指针(单向链表)或者两个指针(双向链表),链表是一种动态的数据结构,可以动态的增删节点。它的特点是插入与删除数据十分方便,但寻找与读取数据的表现欠佳。
二、链表的特点
动态内存分配:链表中的节点是在运行时动态创建的,可以根据需要分配和释放内存。
可扩展性:链表的大小可以根据需要动态增长或缩小,没有固定的大小限制。
非连续存储:链表中的节点可以分散在内存的不同位置,每个节点包含数据和指向下一个节点的指针
三,单向链表
在线性表中,每个元素最多只有一个前驱结点和后继结点,采样链式存储时,每个结点需要包含前驱结点或者后继结点的地址信息,其中最简单也是最常用的方法是只存储每个结点的后继结点的地址,以这种方式构成的链表称为单链表。每个结点同时包含前驱节点和后继结点的地址构成的链表称为双链表
链表它是由一个一个节点连接起来的。每一个节点里面有两个值,data存放的是数据,next存放的是 下一个节点的地址。
以下是一个简单的 Java 实现的单链表。这个实现包括基本的操作,如添加节点、显示链表和查找节点。
//节点类
class Node {
int data; // 节点数据
Node next; // 指向下一个节点的引用
// 构造函数
Node(int data) {
this.data = data;
this.next = null;
}
}
//单链表类
class SinglyLinkedList {
private Node head; // 链表头部
// 构造函数
public SinglyLinkedList() {
head = null;
}
// 添加节点到链表尾部
public void append(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;//如果链表为空,插入的数据为头结点
} else {
Node current = head;//头结点赋值给current
while (current.next != null) {//当当前节点的下一个指向不为空时,继续循环
current = current.next;
}//直到下一个节点为空,
current.next = newNode;//插入数据
}
}
// 显示链表
public void display() {
Node current = head;//头结点赋值给current
while (current != null) {//当节点不为空的时候,进入循环输出
System.out.print(current.data + " -> ");
current = current.next;//改变节点到下一个节点
}
System.out.println("null");
}
// 查找节点
public boolean find(int data) {
Node current = head;//头结点赋值给current
while (current != null) {
if (current.data == data) {//当所要查找的data和链表中的current.data对应时,返回
return true;
}
current = current.next;//当不对应时,继续下一个
}
return false;
}
}
//单链表测试类
public class LinkedListTest {
public static void main(String[] args) {
SinglyLinkedList list = new SinglyLinkedList();
// 添加节点
list.append(10);
list.append(20);
list.append(30);
// 显示链表
list.display();
// 查找节点
System.out.println("查找20: " + list.find(20));
System.out.println("查找40: " + list.find(40));
}
}
四,双向链表
双向链表中同样有数据域和指针域。不同之处在于,指针域有左右(或上一个、下一个)之分,用来连接上一个结点、当前结点、下一个结点。
每个结点存在两个指针域,分别存储该结点的前驱结点引用和后继结点引用,从任意一个结点出发,都能通过前驱引用以及后继引用完成整个链表结点的访问。
所以不难看出,单向链表能干的事,双向链表也能干!但是正是因为这一特性,相比于单链表,双向链表在访问其他结点上带来方便的同时,将占用更多的资源,因此在使用的时候可以根据自己的场景来决定使用何种数据结构。
以下是一个简单的 Java 实现的双向链表。双向链表每个节点都有两个引用:一个指向前一个节点,一个指向下一个节点。
//节点类
class DoublyNode {
int data; // 节点数据
DoublyNode next; // 指向下一个节点的引用
DoublyNode prev; // 指向前一个节点的引用
// 构造函数
DoublyNode(int data) {
this.data = data;
this.next = null;
this.prev = null;
}
}
//双向链表类
class DoublyLinkedList {
private DoublyNode head; // 链表头部
private DoublyNode tail; // 链表尾部
// 构造函数
public DoublyLinkedList() {
head = null;
tail = null;
}
// 添加节点到链表尾部
public void append(int data) {
DoublyNode newNode = new DoublyNode(data);
if (head == null) {
head = newNode;
tail = newNode;
} else {
tail.next = newNode;
newNode.prev = tail;
tail = newNode;
}
}
// 显示链表从头到尾
public void displayForward() {
DoublyNode current = head;
while (current != null) {
System.out.print(current.data + " <-> ");
current = current.next;
}
System.out.println("null");
}
// 显示链表从尾到头
public void displayBackward() {
DoublyNode current = tail;
while (current != null) {
System.out.print(current.data + " <-> ");
current = current.prev;
}
System.out.println("null");
}
// 查找节点
public boolean find(int data) {
DoublyNode current = head;
while (current != null) {
if (current.data == data) {
return true;
}
current = current.next;
}
return false;
}
}
//测试双向链表
public class DoublyLinkedListTest {
public static void main(String[] args) {
DoublyLinkedList list = new DoublyLinkedList();
// 添加节点
list.append(10);
list.append(20);
list.append(30);
// 显示链表
System.out.print("从头到尾: ");
list.displayForward();
System.out.print("从尾到头: ");
list.displayBackward();
// 查找节点
System.out.println("查找20: " + list.find(20));
System.out.println("查找40: " + list.find(40));
}
}