链表是一种重要的数据结构,包含单向链表和双向链表:
1. 单向链表
单链表(单向链表):由两部分组成 数据域(Data)和结点域(Node),单链表就像是一条打了很多结的绳子,每一个绳结相当于一个结点,每个节结点间都有绳子连接,这样原理的实现是通过Node结点区的头指针head实现的,每个结点都有一个指针,每个节点指针的指向都是指向自身结点的下一个结点,最后一个结点的head指向为null,这样一来就连成了上述所说绳子一样的链,对单链表的操作只能从一端开始,如果需要查找链表中的某一个结点,则需要从头开始进行遍历。

| Linklist类: |
|---|
package linklist;
public class Linklist {
// 用来存取该节点的数据,public修饰符不用get set方法
public int data = 99999999; //数值
// 用来存储下个节点
public Linklist next; //节点
/**
* 添加
* @param data 要添加的值
*/
public void add(int data) {
//如果next为空,就给它赋值
if(next ==null) {
next = new Linklist();
next.data = data;
}else {
//如果不为空,就让next去添加
next.add(data);
}
}
/**
* 删除
* @param data 要删除的数据
*/
public void delete(int data) {
// 如果下一个为空,那么程序退出
if(next == null) {
return;
}
Linklist temp;
temp = next;
if(temp.data == data) {
next = temp.next;
temp.next = null;
}else {
next.delete(data);
}
}
/**
* 查找
* @param data 要查找的数据
* @return
*/
public Linklist find(int data) {
if(next == null) {
return null;
}
if(next.data == data) {
return next;
}else {
return next.find(data);
}
}
/**
* 更新
* @param data 更新数据
* @param newdata
*/
public void update(int data,int newData) {
Linklist find = find(data);
find.data = newData;
}
@Override
public String toString() {
return "Linklist [data=" + data + ", next=" + next + "]";
}
}
| LinklistTest类: |
|---|
package linklist;
public class LinklistTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Linklist a = new Linklist();
a.add(5);
a.add(6);
a.add(59);
a.add(-5);
a.add(9999999);
a.add(58);
a.add(-655);
System.out.println(a);
a.delete(58);
Linklist b = a.find(59);
System.out.println(b);
Linklist c = a.find(-5);
System.out.println(c);
a.update(9999999, 99);
System.out.println(a);
}
}
运行结果:

2. 双向链表
双链表(双向链表):双链表和单链表相比,多了一个指向尾指针(tail),双链表的每个结点都有一个头指针head和尾指针tail,双链表相比单链表更容易操作,双链表结点的首结点的head指向为null,tail指向下一个节点的tail;尾结点的head指向前一个结点的head,tail 指向为null,是双向的关系;

| DoublyLinkList类: |
|---|
package com.wwy.linklist;
import java.io.IOException;
public class DoublyLinkList{
//头
private Link frist;
//尾
private Link last;
//初始化首尾指针
public DoublyLinkList(){
frist = null;
last = null;
}
public boolean isEmpty(){
return frist == null;
}
public void addFrist(int value){
Link newLink= new Link(value);
// 如果链表为空
if(isEmpty()){
last = newLink; //last -> newLink
}else {
frist.pre = newLink; // frist.pre -> newLink
}
newLink.next = frist; // newLink -> frist
frist = newLink; // frist -> newLink
}
public void addLast(int value){
Link newLink= new Link(value);
// 如果链表为空
if(isEmpty()){
frist = newLink; // 表头指针直接指向新节点
}else {
last.next = newLink; //last指向的节点指向新节点
newLink.pre = last; //新节点的前驱指向last指针
}
last = newLink; // last指向新节点
}
public boolean addBefore(int key,int value){
Link cur = frist;
if(frist.next.val == key){
addFrist(value);
return true;
}else {
while (cur.next.val != key) {
cur = cur.next;
if(cur == null){
return false;
}
}
Link newLink= new Link(value);
newLink.next = cur.next;
cur.next.pre = newLink;
newLink.pre = cur;
cur.next = newLink;
return true;
}
}
public void addAfter(int key,int value)throws RuntimeException{
Link cur = frist;
while(cur.val!=key){ //经过循环,cur指针指向指定节点
cur = cur.next;
if(cur == null){ // 找不到该节点
throw new RuntimeException("Node is not exists");
}
}
Link newLink = new Link(value);
if (cur == last){ // 如果当前结点是尾节点
newLink.next = null; // 新节点指向null
last =newLink; // last指针指向新节点
}else {
newLink.next = cur.next; //新节点next指针,指向当前结点的next
cur.next.pre = newLink; //当前结点的前驱指向新节点
}
newLink.pre = cur;//当前结点的前驱指向当前结点
cur.next = newLink; //当前结点的后继指向新节点
}
public void deleteFrist(){
if(frist.next == null){
last = null;
}else {
frist.next.pre = null;
}
frist = frist.next;
}
public void deleteLast(int key){
if(frist.next == null){
frist = null;
}else {
last.pre.next = null;
}
last = last.pre;
}
public void deleteKey(int key)throws RuntimeException{
Link cur = frist;
while(cur.val!= key){
cur = cur.next;
if(cur == null){ //不存在该节点
throw new RuntimeException("Node is not exists");
}
}
if(cur == frist){ // 如果frist指向的节点
frist = cur.next; //frist指针后移
}else {
cur.pre.next = cur.next;//前面节点的后继指向当前节点的后一个节点
}
if(cur == last){ // 如果当前节点是尾节点
last = cur.pre; // 尾节点的前驱前移
}else {
cur.next.pre = cur.pre; //后面节点的前驱指向当前节点的前一个节点
}
}
public int queryPre(int value)throws IOException,RuntimeException{
Link cur = frist;
if(frist.val == value){
throw new RuntimeException("Not find "+value+"pre");
}
while(cur.next.val!=value){
cur = cur.next;
if(cur.next == null){
throw new RuntimeException(value +"pre is not exeist!");
}
}
return cur.val;
}
public void displayForward(){
Link cur = frist;
while(cur!=null){
cur.displayCurrentNode();
cur = cur.next;
}
System.out.println();
}
public void displayBackward(){
Link cur = last;
while(cur!=null){
cur.displayCurrentNode();
cur = cur.pre;
}
System.out.println();
}
}
| Test类: |
|---|
package com.wwy.linklist;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException, RuntimeException {
// TODO Auto-generated method stub
// public void test()throws Exception{ // 自己测试代码
DoublyLinkList d = new DoublyLinkList();
d.addFrist(1);
// d.addFirst(1);
d.addFrist(2);
d.addFrist(3);
d.addLast(6);
d.addFrist(4);
d.addFrist(5);
d.addLast(7);
d.displayForward();
// System.out.println(d.queryPre(4));
// System.out.println(d.queryPre(2));
System.out.println(d.queryPre(3));
System.out.println(d.queryPre(7));
System.out.println(d.queryPre(6));
d.addBefore(6, 9);
d.displayBackward();
d.deleteKey(3);
d.displayBackward();
}
}
class Link {
public int val;
public Link next;
public Link pre;
public Link(int val) {
this.val = val;
}
public void displayCurrentNode() {
System.out.print(val + " ");
}
}
运行结果:

本文深入探讨了链表这一核心数据结构,包括单向链表和双向链表的原理及操作,如添加、删除、查找和更新等。通过具体代码示例,详细解释了链表的实现方式和运行结果。
828

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



