单链表应用

一. 链表介绍

  1. 链表是以节点的方式来存储的,是链式存储。
  2. 每个节点包含data域和next域,next域指向下一个节点。
  3. 链表的各个节点不一定是连续存储。
  4. 链表分为带头节点的链表和没有头节点的链表,根据实际需求来确定。

二. 单链表应用实例的代码实现

  1. 节点
package datastructure.linkedlist.simplelinkedlist;

public class HeroNode {

    public int no;   // 编号
    public String name; // 姓名
    public HeroNode next; // 下一个节点

    public HeroNode() {
    }

    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }

}
  1. 链表
package datastructure.linkedlist.simplelinkedlist;

import java.util.Stack;

// 单链表
public class SimpleLinkedList {

    // 头节点
    private HeroNode head = new HeroNode(0, "");

    // 头结点的get方法
    public HeroNode getHead() {
        return head;
    }

    // 添加节点
    public void add(HeroNode heroNode) {
        HeroNode temp = head;
        // 把要添加的节点添加到链表的最后面
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = heroNode;
    }

    // 按照编号顺序添加节点
    public void addByOrder(HeroNode heroNode) {
        HeroNode temp = head;
        // 用来判断节点编号有没有重复  true为重复
        boolean flag = false;
        // 为要添加的节点找合适的位置
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.no > heroNode.no) {
                break;
            } else if (temp.next.no == heroNode.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            System.out.println("节点编号重复!");
        } else {
            // 如果节点编号没有重复,就将要添加的节点插入到链表中合适的位置
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }

    // 删除节点
    public void delete(int heroNo) {
        HeroNode temp = head;
        // 用来判断链表中有没有要删除的节点
        boolean flag = false;
        // 寻找要删除节点的前一个节点
        while (true) {
            if (temp.next == null) {
                System.out.println("没有要删除的这个节点!");
                break;
            }
            if (temp.next.no == heroNo) {
                // 链表中存在要删除的节点
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            // 把要删除节点的前一个节点的next指向要删除节点的next (断开要删除节点在链表中的连接)
            temp.next = temp.next.next;
        }
    }


    // 修改节点数据
    public void update(HeroNode heroNode) {
        HeroNode temp = head.next;
        // 用来判断有没有找到要修改的节点
        boolean flag = false;
        // 在链表中寻找要修改的节点
        while (true) {
            if (temp == null) {
                System.out.println("没有要修改的这个节点!");
                break;
            }
            if (temp.no == heroNode.no) {
                // 找到要修改的节点
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            // 修改节点的信息 (当前节点中只需要修改name)
            temp.name = heroNode.name;
        }
    }

    // 遍历所有节点
    public void allNode() {
        HeroNode temp = head.next;
        if (temp == null) {
            System.out.println("此链表为空链表!");
            return;
        }
        while (true) {
            System.out.println(temp);
            temp = temp.next;
            if (temp == null) {
                break;
            }
        }
    }

    // 返回单链表的长度
    public int getLength(HeroNode headNode) {
        if (headNode.next == null) {
            return 0;
        }
        // 记录链表的长度
        int length = 0;
        HeroNode temp = headNode.next;
        while (temp != null) {
            length ++;
            temp = temp.next;
        }
        return length;
    }

    // 获取倒数第N个节点
    public HeroNode getLastIndexNode(HeroNode headNode, int index) {
        // 如果链表为空,返回null
        if (headNode.next == null) {
            return null;
        }
        // 如果传入的index不符合要求,
        int length = getLength(headNode);
        if (index <= 0 || index > length) {
            System.out.println("获取失败!");
            return null;
        }
        // 寻找链表中倒数第index个节点并返回+
        HeroNode currentNode = headNode.next;
        for (int i = 0; i < length - index; i++) {
            currentNode = currentNode.next;
        }
        return currentNode;
    }

    // 单链表的反转
    public void reverse(HeroNode headNode) {
        // 头节点不算  如果链表中没有节点或者只有一个节点,直接return
        if (headNode.next == null || headNode.next.next == null) {
            return;
        }
        HeroNode currentNode = headNode.next;
        HeroNode nextNode = null;
        // 创建一个新的头节点 相当于创建一条新的链表
        HeroNode reverseHead = new HeroNode(0, "");
        // 不断地把旧链表的下一个节点 插入到新链表的头节点和第一个节点之间
        while (currentNode != null) {
            nextNode = currentNode.next;        // 记录当前节点的下一个节点
            currentNode.next = reverseHead.next;  // 把新链表接到当前节点的后面(也就是把当前节点接到新链表的第一个节点之前)
            reverseHead.next = currentNode;        // 当前节点接到新链表的头节点之后
            currentNode = nextNode;             // 向下进行
        }
        // 把新链表接到原来链表的头节点上
        headNode.next = reverseHead.next;
    }

    // 单链表的逆序打印的第一种方法  两次反转 遍历打印
    public void reversePrint1(HeroNode headNode) {
        // 反转链表
        reverse(headNode);
        // 打印所有节点
        allNode();
        // 把链表反转回去
        reverse(headNode);
    }

    // 单链表的逆序打印 第二种方法    利用栈stack 不改变原来单链表的数据结构
    public void reversePrint2(HeroNode headNode) {
        if (headNode.next == null) {
            return;
        }
        HeroNode current = headNode.next;
        Stack<HeroNode> stack = new Stack<>();
        // 把每个节点按链表的顺序压入栈中
        while (current != null) {
            stack.push(current);
            current = current.next;
        }
        // 逐个出栈  先进后出
        while (stack.size() > 0) {
            System.out.println(stack.pop());
        }
    }

    // 有序合并两个有序的单链表
    public void mergeTwoSimpleLinkedList(HeroNode headNode1, HeroNode headNode2) {
        // 如果有一个链表为空或者都为空,说明不用合并 直接return
        if (headNode1.next == null && headNode2.next == null) {
            return;
        } else if (headNode1.next == null) {
            return;
        } else if (headNode1.next == null) {
            return;
        }

        // 把第一个链表接到新链表上
        HeroNode current = headNode1.next;
        HeroNode nextNode = null;
        while (current != null) {
            nextNode = current.next;   // 记录下一个节点
            current.next = null;       // 把当前节点断开连接置为单独的节点
            addByOrder(current);      // 按照顺序添加到新的链表上
            current = nextNode;       // 向下进行
        }

        // 遍历第二个链表有序添加到新链表上
        current = headNode2.next;
        while (current != null) {
            nextNode = current.next;
            current.next = null;
            addByOrder(current);
            current = nextNode;
        }
    }

}
  1. 测试类
package datastructure.linkedlist.simplelinkedlist;

public class SimpleLinkedListDemo {

    public static void main(String[] args) {
        HeroNode heroNode1 = new HeroNode(1, "宋江");
        HeroNode heroNode2 = new HeroNode(2, "卢俊义");
        HeroNode heroNode3 = new HeroNode(3, "吴用");
        HeroNode heroNode4 = new HeroNode(4, "林冲");

        /*// 创建一个单链表
        SimpleLinkedList simpleLinkedList = new SimpleLinkedList();
        // 向单链表添加节点
        simpleLinkedList.addByOrder(heroNode1);
        simpleLinkedList.addByOrder(heroNode3);
        simpleLinkedList.addByOrder(heroNode2);
        simpleLinkedList.addByOrder(heroNode4);
        // 遍历单链表
        System.out.println("原单链表是这样的:");
        simpleLinkedList.allNode();*/

        SimpleLinkedList simpleLinkedList1 = new SimpleLinkedList();
        SimpleLinkedList simpleLinkedList2 = new SimpleLinkedList();
        /*simpleLinkedList1.addByOrder(heroNode3);
        simpleLinkedList1.addByOrder(heroNode1);*/
        simpleLinkedList1.addByOrder(heroNode4);
        simpleLinkedList1.addByOrder(heroNode2);
        simpleLinkedList2.addByOrder(heroNode3);
        simpleLinkedList2.addByOrder(heroNode1);
        // 遍历第一个单链表
        System.out.println("第一个链表:");
        simpleLinkedList1.allNode();
        // 遍历第一个单链表
        System.out.println("第二个链表:");
        simpleLinkedList2.allNode();
        // 合并两个链表并遍历
        System.out.println("合并后的链表:");
        SimpleLinkedList simpleLinkedList = new SimpleLinkedList();
        simpleLinkedList.mergeTwoSimpleLinkedList(simpleLinkedList1.getHead(), simpleLinkedList2.getHead());
        simpleLinkedList.allNode();

        /*// 逆序输出链表
        System.out.println("两次反转方法,逆序打印链表。。。");
        simpleLinkedList.reversePrint1(simpleLinkedList.getHead());
        System.out.println("利用栈逆序打印链表。。。");
        simpleLinkedList.reversePrint2(simpleLinkedList.getHead());*/

        /*// 反转单链表
        simpleLinkedList.reverse(simpleLinkedList.getHead());
        // 遍历单链表
        System.out.println("反转之后的链表是这样的:");
        simpleLinkedList.allNode();*/

        /*// 遍历单链表
        simpleLinkedList.allNode();
        // 修改单链表的某个节点
        System.out.println("修改单链表之后:");
        HeroNode heroNode = new HeroNode(2, "小卢");
        simpleLinkedList.update(heroNode);
        // 遍历单链表
        simpleLinkedList.allNode();
        // 删除节点
        simpleLinkedList.delete(3);
        // simpleLinkedList.delete(2);
        // simpleLinkedList.delete(1);
        // simpleLinkedList.delete(4);
        System.out.println("删除节点后:");
        // 遍历节点
        simpleLinkedList.allNode();
        // 查看单链表的节点个数
        int length = simpleLinkedList.getLength(simpleLinkedList.getHead());
        System.out.println("这个链表的节点个数为" + length);
        // 查看倒数第N个节点
        HeroNode currentNode = simpleLinkedList.getLastIndexNode(simpleLinkedList.getHead(), 2);
        System.out.println(currentNode);*/

    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的单链表应用实例代码,使用C语言实现: ```c #include <stdio.h> #include <stdlib.h> // 定义链表结构体 typedef struct Node { int data; struct Node* next; } node; // 创建新节点 node* create_node(int data) { node* new = (node*)malloc(sizeof(node)); new->data = data; new->next = NULL; return new; } // 在链表末尾插入节点 void insert_node(node** head, int data) { node* new = create_node(data); if (*head == NULL) { *head = new; return; } node* current = *head; while (current->next != NULL) { current = current->next; } current->next = new; } // 删除指定值的节点 void delete_node(node** head, int data) { if (*head == NULL) { return; } if ((*head)->data == data) { node* temp = *head; *head = (*head)->next; free(temp); return; } node* current = *head; while (current->next != NULL && current->next->data != data) { current = current->next; } if (current->next != NULL) { node* temp = current->next; current->next = current->next->next; free(temp); } } // 打印链表 void print_list(node* head) { printf("Linked List: "); while (head != NULL) { printf("%d ", head->data); head = head->next; } printf("\n"); } int main() { node* head = NULL; insert_node(&head, 1); insert_node(&head, 2); insert_node(&head, 3); insert_node(&head, 4); insert_node(&head, 5); print_list(head); delete_node(&head, 3); print_list(head); delete_node(&head, 1); print_list(head); return 0; } ``` 该代码实现了一个单链表的基本操作,包括创建节点、在末尾插入节点、删除指定值的节点和打印链表。可以通过在 `main` 函数中调用这些函数来使用这个单链表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值