一.链表概述
1.定义
在计算机科学中,链表是数据元素的线性集合,其每个元素都指向下一个元素,元素上存储不连续。



2.单向链表代码实现
package com.SinglyLinkedList;
public class SingLinkedList {
private Node head = null;//头指针
//节点类(内部类,对外暴露少)
private static class Node {
int value;//节点值
Node next;//下一个节点指针
//构造方法
public Node(int value,Node next) {
this.next = next;
this.value = value;
}
}
//添加节点
public void addFirst(int value) {
//1.链表为空
//head = new Node(value,null);
//2.链表不为空
head = new Node(value, head);//这个代码能处理链表非空和链表为空的情况
}
//遍历链表
public void loop1(int[] arr){
Node p = head;//创建一个指针p,指向头指针head
while (p != null){
System.out.print(p.value+" ");
p = p.next;//移动指针让p指向下一个节点,直到p为null
}
}
public void loop2(int[] arr){
for (Node p = head; p != null; p = p.next) {
System.out.print(p.value+" ");
}
}
//查找最后一个节点
private Node findLast(int value){
if (head == null){//链表为空的情况
return null;
}
Node p = head;
for(; p != null; p = p.next){
if (p.value == value){
return p;
}
}
return p;
}
//添加最后一个节点
public void addLast(int value){
Node last = findLast(value);
if (last == null){
addFirst(value);
}else {
last.next = new Node(value,null);
}
}
//查找索引值
private Node findNode(int index){
int i = 0;
for (Node p = head;p != null;p = p.next,i++) {
if (i == index){
return p;//索引值存在,返回该节点
}
}
return null;//索引值不存在
}
//获取索引值
public void get(int index){
Node node = findNode(index);
if (node != null){
System.out.println(node.value);
}else {
System.out.println("索引值不存在");
}
}
//往链表的任意一个索引位置加入一个新的元素
public void insert(int index,int value){
if (index == 0){
addFirst(value);//添加第一个节点
}
Node node = findNode(index - 1);//表示上一个节点
if (node == null){//索引值不存在的情况
addFirst(value);
return;
}
node.next = new Node(value,node.next);//创建一个新节点,插入到指定位置
}
//删除第一个位置的索引值
public void removeFirst(){
if (head == null){//链表为空的情况
return;
}
head = head.next;//让head指向第二个节点
}
//按索引位置来进行删除
public void remove(int index){
if (index == 0){ //索引值为0的情况
removeFirst();//删除第一个节点
return;
}
Node node = findNode(index - 1);//上一个节点
// 如果当前节点为空,则移除链表的第一个节点并返回
if (node == null){ //索引值不存在的情况
removeFirst();
return;
}
// 获取要被删除的下一个节点
Node removed = node.next;
// 如果要删除的节点为空,则直接返回
if (removed == null){ //索引值不存在的情况
return;
}
node.next = removed.next;//删除指定位置的节点
}
//单向链表(带哨兵)
private static class SinglyLinkedList {
private Node head = new Node(0,null);
}
}
什么时候要加static?
当某一个内部类使用了外部类的一个成员变量时,就不能加static;而当内部类是相对独立的,跟外部类的成员变量没有任何关系时,这时候就可以加static。
3.带哨兵节点
package com.SinglyLinkedList;
public class SingLinkedList {
private Node head = new Node(666,null);//头指针
//节点类(内部类,对外暴露少)
private static class Node {
int value;//节点值
Node next;//下一个节点指针
//构造方法
public Node(int value,Node next) {
this.next = next;
this.value = value;
}
}
//添加节点
public void addFirst(int value) {
/* //1.链表为空
//head = new Node(value,null);
//2.链表不为空
head = new Node(value, head);//这个代码能处理链表非空和链表为空的情况*/
insert(0,value);
}
//遍历链表
public void loop1(int[] arr){
Node p = head.next;//创建一个指针p,指向头指针head的下一个节点,跳过了头指针
while (p != null){
System.out.print(p.value+" ");
p = p.next;//移动指针让p指向下一个节点,直到p为null
}
}
public void loop2(int[] arr){
for (Node p = head.next; p != null; p = p.next) {//要从哨兵的下一个元素开始遍历
System.out.print(p.value+" ");
}
}
//查找最后一个节点
private Node findLast(int value){
/* if (head == null){//链表为空的情况
return null;
}*/
Node p = head;
for(; p != null; p = p.next){
if (p.value == value){
return p;
}
}
return p;
}
//添加最后一个节点
public void addLast(int value){
/* Node last = findLast(value);
if (last == null){
addFirst(value);
}else {
last.next = new Node(value,null);
}*/
Node last = findLast(value);
last.next = new Node(value,null);
}
//查找索引值
private Node findNode(int index){
int i = -1;
for (Node p = head;p != null;p = p.next,i++) {
if (i == index){
return p;//索引值存在,返回该节点
}
}
return null;//索引值不存在
}
//获取索引值
public void get(int index){
Node node = findNode(index);
if (node != null){
System.out.println(node.value);
}else {
System.out.println("索引值不存在");
}
}
//往链表的任意一个索引位置加入一个新的元素
public void insert(int index,int value){
/* if (index == 0){
addFirst(value);//添加第一个节点
}*/
Node node = findNode(index - 1);//表示上一个节点
if (node == null){//索引值不存在的情况
addFirst(value);
return;
}
node.next = new Node(value,node.next);//创建一个新节点,插入到指定位置
}
//删除第一个位置的索引值
public void removeFirst(){
/* if (head == null){//链表为空的情况
return;
}
head = head.next;//让head指向第二个节点*/
remove(0);
}
//按索引位置来进行删除
public void remove(int index){
/* if (index == 0){ //索引值为0的情况
removeFirst();//删除第一个节点
return;
}*/
Node node = findNode(index - 1);//上一个节点
// 如果当前节点为空,则移除链表的第一个节点并返回
if (node == null){ //索引值不存在的情况
removeFirst();
return;
}
// 获取要被删除的下一个节点
Node removed = node.next;
// 如果要删除的节点为空,则直接返回
if (removed == null){ //索引值不存在的情况
return;
}
node.next = removed.next;//删除指定位置的节点
}
//单向链表(带哨兵)
private static class SinglyLinkedList {
private Node head = new Node(0,null);
}
}
二.双向链表
package com.SinglyLinkedList;
import org.w3c.dom.Node;
public class DoublyLinkedSentinel {
private Node head;//头指针
private Node tail;//尾指针
static class Node{
Node prev;//上一个节点指针
int value;//节点值
Node next;//下一个节点指针
public Node(Node prev, int value, Node next) {
this.value = value;
this.prev = prev;
this.next = next;
}
}
//创建一个头尾指针
public DoublyLinkedSentinel(){
head = new Node(null,666,null);
tail = new Node(null,888,null);
}
//查找指定位置的节点
private Node findNode(int index){
int i = -1;
for(Node p = head;p !=tail; p = p.next,i++){
if (i == index){
return p;
}
}
return null;
}
//添加首节点
public void addFirst(int value){
}
//删除节点
public void removeFirst(){
remove(0);
}
//添加尾节点
public void addLast(int value){
Node last = tail.prev;
Node addad = new Node(last,value,tail);
last.next = addad;
tail.prev = addad;
}
//删除尾节点
public void removeLast(){
Node removed = tail.prev;//通过伪哨兵拿到最后一个节点
if (removed == head){//当删除的节点为头节点时
//抛异常
throw new RuntimeException("链表为空");
}
Node prev = removed.prev;//拿到前一个节点
prev.next = tail;//让上一个节点指向伪哨兵
tail.prev = prev;//再让伪哨兵的prev节点指向前一个节点
}
//添加指定位置的节点
public void insert(int index,int value){
Node prev = findNode(index - 1);
if (prev == null){
//抛异常
throw new RuntimeException("链表为空");
}
Node next = prev.next;
Node inserted = new Node(prev,value,next);//新节点
prev.next = inserted;
next.prev = inserted;
}
//删除指定位置的节点
public void remove(int index){
Node prev = findNode(index -1);
if (prev == null){//索引值为空的情况下
//抛异常
throw new RuntimeException("链表为空");
}
Node removed = prev.next;
if (removed == tail){//当删除的节点为哨兵节点时
//抛异常
throw new RuntimeException("索引值不存在");
}
Node next = removed.next;
prev.next = next;
next.prev = prev;
}
}
三.双向环形链表
package com.SinglyLinkedList;
public class DoublyLinkedListSentinel2 {
private static class Node {
Node prev;
int value;
Node next;
public Node(Node prev, int value, Node next) {
this.prev = prev;
this.value = value;
this.next = next;
}
}
private Node sentinel = new Node(null, -1, null);
public DoublyLinkedListSentinel2() {
// 创建哨兵节点并让它指向自己形成环形结构
sentinel.prev = sentinel;
sentinel.next = sentinel;
}
// 添加到第一个节点
public void addFirst(int value) {
Node a = sentinel;
Node b = sentinel.next;
Node added = new Node(a, value, b);
a.next = added;
b.next = added;
}
// 添加到最后一个节点
public void addLast(int value) {
Node a = sentinel.prev;
Node b = sentinel;
Node added = new Node(a, value, b);
a.next = added;
b.prev = added;
}
// 删除第一个节点
public void removeFirst() {
Node removed = sentinel.next;
if (removed == sentinel) {
throw new RuntimeException("List is empty");
}
Node a = sentinel;
Node b = removed.next;
a.next = b;
b.prev = a;
}
// 删除最后一个节点
public void removeLast() {
Node removed = sentinel.prev;
if (removed == sentinel){
throw new RuntimeException("List is empty");
}
Node a = removed.prev;
Node b = sentinel;
a.next = b;
b.prev = a;
}
// 查找值
public Node findByvalue(int value){
Node p = sentinel.next;
while (p != sentinel){
if (p.value == value){
return p;
}
p = p.next;
}
return null;
}
//根据值来进行删除
public void remove(int value){
Node removed = findByvalue(value);
if (removed == null){
return;
}
Node a = removed.prev;
Node b = removed.next;
a.next = b;
b.prev = a;
}
}

368

被折叠的 条评论
为什么被折叠?



