线性结构---链表算法程序

 程序内有写详细备注,请了解链表的结构后观看

初始化链表

void initLinkedList(LinkedList *list)

返回链表的长度

size_t getLength(const LinkedList *list)

在指定位置插入元素

void insertAt(LinkedList *list, size_t index, int element)

在末尾插入元素

void insertEnd(LinkedList *list, int element)

删除指定位置的元素并返回被删除的元素

int deleteAt(LinkedList *list, size_t index)

删除末尾元素

int deleteEnd(LinkedList *list)

获取指定位置的元素

int getElementAt(const LinkedList *list, size_t index)

修改指定位置的元素

void modifyAt(LinkedList *list, size_t index, int newValue)

释放链表内存

void destroyLinkedList(LinkedList *list)

#include <stdio.h>
#include <stdlib.h>

// 链表节点结构
typedef struct Node
{
    int data;          // 节点存储的数据
    struct Node *next; // 指向下一个节点的数据(结构体指针)嵌套自己指向自己
} Node;

// 头节点,链表结构
typedef struct
{
    Node *head;  // 指针变量,头节点指针指向首元节点(带数据的)
    size_t size; // 头节点中的数据是链表中的节点个数
} LinkedList;

// 初始化链表
void initLinkedList(LinkedList *list)
{
    list->head = NULL; // 初始化头节点为空,截断链表
    list->size = 0;    // 初始化节点个数为0
}

// 返回链表的长度
size_t getLength(LinkedList *list)
{
    return list->size; // 返回链表的节点个数
}

// 在指定位置插入元素
void insertAt(LinkedList *list, size_t index, int element)
{
    if (index < 0 || index > list->size)
    {
        printf("输入的index数据非法\n");
        return;
    }

    // 插入数据的过程
    // 1、将数据封装到Node结构体的变量中
    Node *newNode = (Node *)malloc(sizeof(Node)); // 创建新节点
    newNode->data = element;

    if (index == 0)
    {
        newNode->next = list->head; // 现在由新节点指针指向带数据的首元节点
        list->head = newNode;       // 将结点newNode赋值给list的后继结点,让头节点指针指向新节点数据
    }
    else
    {
        Node *prevNode = list->head; // 创建指针变量,令prevNode指向首元节点

        for (size_t i = 0; i < index - 1; i++) // 指针已经在首元节点若在1处插入不用循环,故减1
        {
            prevNode = prevNode->next; // 链式结构不断的指向下一个
        }

        newNode->next = prevNode->next; // 让新节点指针指向后节点数据
        prevNode->next = newNode;       // 让前节点指针指向新节点数据
    }

    list->size++; // 更新节点数
}

// 在末尾插入元素
void insertEnd(LinkedList *list, int element)
{
    insertAt(list, list->size, element); // 在链表末尾插入元素
}

// 删除指定位置的元素并返回被删除的元素
int deleteAt(LinkedList *list, size_t index)
{
    if (index >= list->size)
    {
        return -1; // 忽略无效的删除位置
    }

    int deletedElement;

    if (index == 0)
    {
        Node *temp = list->head;     // 定义指针变量令temp指向首元节点(第一个带数据的节点)
        list->head = temp->next;     // 令头节点指向下一个节点跳过首元节点
        deletedElement = temp->data; // 赋值
        free(temp);                  // 释放被删除节点的内存
    }
    else
    {
        Node *prevNode = list->head; // 定义指针变量令prevNode指向首元节点

        for (size_t i = 0; i < index - 1; i++)
        {
            prevNode = prevNode->next; // 遍历到位置
        }

        Node *temp = prevNode->next; // 定义指针变量令temp指向下个数据节点
        prevNode->next = temp->next; // 跳过节点
        deletedElement = temp->data; // 存储
        free(temp);                  // 释放被删除节点的内存
    }

    list->size--;
    return deletedElement;
}

// 获取指定位置的元素
int getElementAt(const LinkedList *list, size_t index)
{
    if (index >= list->size)
    {
        return -1; // 返回无效的索引
    }

    Node *currentNode = list->head;    // 指向首元节点
    for (size_t i = 0; i < index; i++) // 插入、删除index需要减一
    {
        currentNode = currentNode->next; // 遍历找到位置,当index=1时需要运行一次刚好到
    }

    return currentNode->data; // 返回指定位置的元素
}

// 修改指定位置的元素
void modifyAt(LinkedList *list, size_t index, int newValue)
{
    if (index >= list->size)
    {
        return; // 忽略无效的修改位置
    }

    Node *currentNode = list->head; // 指向首元节点

    for (size_t i = 0; i < index; i++)
    {
        currentNode = currentNode->next; // 遍历找到位置,当index=1时需要运行一次刚好到
    }

    currentNode->data = newValue; // 修改节点的值
}

// 释放链表内存
void destroyLinkedList(LinkedList *list)
{
    Node *currentNode = list->head; // 指向首元节点
    while (currentNode != NULL)     // 最后的节点为空
    {
        Node *temp = currentNode;        // currentNode的值给temp,相当与中间节点释放它链表不受影响
        currentNode = currentNode->next; // 令下一个节点数值赋值给currentNode
        free(temp);                      // 释放temp节点的内存,一个一个释放直到结束
    }

    list->head = NULL; // 头节点置为空
    list->size = 0;    // 节点个数置为0
}

int main()
{
    LinkedList myList; // 声明链表

    initLinkedList(&myList);
    printf("初始化链表成功!\n");

    insertEnd(&myList, 1); // 链表尾部插入元素1
    insertEnd(&myList, 2); // 链表尾部插入元素2
    printf("向链表插入了2个元素\n");

    printf("链表长度为 %zu\n", getLength(&myList)); // 获取链表长度

    insertAt(&myList, 1, 3); // 在索引1处插入元素3

    printf("在索引1处插入元素3\n");

    printf("链表长度为:%zu\n", getLength(&myList)); // 再次获取链表长度

    printf("索引1处的元素为:%d\n", getElementAt(&myList, 1)); // 获取索引1处的元素

    modifyAt(&myList, 0, 4); // 修改索引0处的元素
    printf("把索引0处的元素修改为4\n");

    printf("索引0处的元素为:%d\n", getElementAt(&myList, 0)); // 获取索引0处的元素

    printf("删除索引1处的元素,该元素是:%d\n", deleteAt(&myList, 1)); // 删除索引1处的元素

    destroyLinkedList(&myList); // 销毁链表
    printf("链表销毁成功!\n");

    printf("链表长度为:%zu\n", getLength(&myList)); // 再次获取链表长度


    getchar();
    return 0;
}

  • 45
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值