单向链表实现

本文详细介绍了单向链表的基本概念、存储原理及三种主要操作:添加、查询和修改。通过Java代码示例展示了如何在链表的头部、尾部及中间插入节点,查询特定节点以及修改节点数据。此外,还讲解了删除操作,包括删除头结点、尾节点和中间节点的方法。
摘要由CSDN通过智能技术生成

1.1 基本介绍

链表(linked list)是一种在物理上非连续、非顺序的数据结构,由若干节点(node)所组成。链表中数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域(data)另一个是存储下一个结点地址的指针域(next)。(百度百科)

1.2 存储原理

链表的每一个节点分布在内存的不同位置,依靠next指针关联起来。这样可以灵活有效地利用零散的碎片空间。链表的第1个节点被称为头节点(3),没有任何节点的next指针指向它,或者说它的前置节点为空头结点用来记录链表的基地址。有了它就可以遍历得到整条链表链表的最后1个节点被称为尾节点(2),它指向的next为NULL

1.3 添加操作

1、思路分析

  • 为了让代码更加精简,统一所有节点的处理逻辑,可以在最前面增加一个虚拟的头结点(不存储数据)
  • 新节点的next指针,指向插入位置的节点。插入位置前置节点的next指针,指向新节点。
  • 只要内存空间允许,能够插入链表的元素是无限的,不需要像数组那样考虑扩容的问题。

头部添加

当链表为空时,头部插入

当链表不为空时,从头部插入。

先让新的节点指向头结点,然后再让头结点指向新节点!!!

尾部添加

先让尾指针指向的节点,指向新节点

然后tail从新指向新节点

中间添加

定义一个指针prev,将prev的当前下一跳给新节点的下一跳。然后再让prev节点重新指向新节点

2、代码示例

接口实现:List

package cn.linkedlist.demo01;

/***
 * List接口方法
 * @param <E>
 */
public interface List<E> extends Iterable<E>{
   
    void add(E element);
    void add(int index, E element) ;
    void remove(E element);
    E remove(int index);
    E get(int index);
    E set(int index, E element) ;
    int size();
    int indexOf(E element) ;
    boolean contains(E element);
    boolean isEmpty();
    void clear();
}

链表实现:LinkedSinglyList

package cn.linkedlist.demo01;

import java.util.Iterator;

public class LinkedSinglyList<E> implements List<E>{
   
    // 创建Node节点
    private class Node{
   
        //数据域 用来存储数据的
        public E data;
        //指针域 用来存储下一个结点对象的地址
        public Node next;

        // 构造方法
        public Node() {
   
            this(null, null);
        }

        public Node(E data) {
   
            this(data, null);
        }

        public Node(E data, Node next) {
   
            this.data = data;
            this.next = next;
        }

        @Override
        public String toString(){
   
            return data.toString();
        }
    }

    // 链表元素的数量
    private int size;
    //链表当中的头指针指向第一个结点对象
    private Node head;
    //链表当中的头指针指向最后一个结点对象
    private Node tail;

    // 初始化链表
    public LinkedSinglyList(){
   
        head = null;
        tail = null;
        size = 0;
    }

    public LinkedSinglyList(E[] arr){
   
        for (E e : arr){
   
            add(e);
        }
    }

    /***
     * 在链表末尾添加新的元素e
     * @param element
     */
    @Override
    public void add(E element) {
   
        add(size, element);
    }

    /***
     * 根据链表的index位置添加新的元素e
     * @param index
     * @param element
     */
    @Override
    public void add(int index, E element) {
   
        if (index < 0|| index > size) {
   
            throw new ArrayIndexOutOfBoundsException("add index out of bounds
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
约瑟夫问题是一个经典的数学问题,它的具体描述是:有n个人围成一圈,从第k个人开始报数,报到m的人出列,然后从下一个人开始重新报数,直到所有人都出列。现在我来介绍一下如何使用C语言的单向链表实现约瑟夫问题。 首先,我们需要定义一个链表节点的结构体,包含两个成员变量:一个是保存人员编号的整型变量,另一个是指向下一个节点的指针。 ```c typedef struct Node { int data; struct Node* next; } Node; ``` 接下来,我们可以编写一个函数来创建一个包含n个节点的循环链表,并返回链表的头节点。 ```c Node* createCircularLinkedList(int n) { Node* head = NULL; Node* prev = NULL; for (int i = 1; i <= n; i++) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = i; if (head == NULL) { head = newNode; } else { prev->next = newNode; } prev = newNode; } prev->next = head; // 将最后一个节点的next指针指向头节点,形成循环链表 return head; } ``` 接下来,我们可以编写一个函数来模拟约瑟夫问题的求解过程。 ```c void josephusProblem(Node* head, int k, int m) { Node* current = head; Node* prev = NULL; // 找到从第k个人开始报数的节点 for (int i = 1; i < k; i++) { prev = current; current = current->next; } // 开始报数并出列,直到所有人都出列 while (current->next != current) { // 报数m次 for (int i = 1; i < m; i++) { prev = current; current = current->next; } // 出列 prev->next = current->next; Node* temp = current; current = current->next; free(temp); } // 输出最后一个出列的人员编号 printf("最后一个出列的人员编号:%d\n", current->data); // 释放头节点的内存 free(current); } ``` 最后,我们可以在主函数中调用上述函数来解决约瑟夫问题。 ```c int main() { int n, k, m; printf("请输入总人数n:"); scanf("%d", &n); printf("请输入从第k个人开始报数:"); scanf("%d", &k); printf("请输入报数m次出列:"); scanf("%d", &m); Node* head = createCircularLinkedList(n); josephusProblem(head, k, m); return 0; } ``` 这样,我们就可以通过C语言的单向链表实现约瑟夫问题了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值