数据结构——线性表之单链表

什么是单链表

单链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针单向链接次序实现的。

程序实例

首先,我们创建一个头文件 Slist.h:

// Slist.h
#ifndef _SLIST_H_
#define _SLIST_H_

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

// 定义单链表节点的数据类型
typedef int SLTDateType;

// 定义单链表节点的结构体
typedef struct SListNode {
    SLTDateType data;               // 存储的数据
    struct SListNode* next;        // 指向下一个节点的指针
} SLNode;

// 动态申请一个节点
SLNode* BuySListNode(SLTDateType x);

// 单链表打印
void SListPrint(SLNode* phead);

// 单链表尾插
void SListPushBack(SLNode** pphead, SLTDateType x);

// 单链表的头插
void SListPushFront(SLNode** pphead, SLTDateType x);

// 单链表的尾删
void SListPopBack(SLNode** pphead);

// 单链表头删
void SListPopFront(SLNode** pphead);

// 单链表查找
SLNode* SListFind(SLNode* phead, SLTDateType x);

// 单链表在pos位置之后插入x
void SListInsertAfter(SLNode* pos, SLTDateType x);

// 单链表在pos位置之后删除x
void SListEraseAfter(SLNode* pos);

// 单链表在pos位置插入x
void SListInsert(SLNode** pphead, SLNode* pos, SLTDateType x);

// 单链表删除pos位置的值
void SListErase(SLNode** pphead, SLNode* pos);

// 释放链表
void SListDestroy(SLNode** pphead);

#endif // _SLIST_H_

接下来,我们实现这些函数在 Slist.c 中:

// Slist.c
#include "Slist.h"

// 动态申请一个节点,返回一个节点首地址
SLNode* BuySListNode(SLTDateType x) {
    SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
    if (newnode == NULL) {
        printf("malloc fail");
        exit(-1);
    }
    newnode->data = x;
    newnode->next = NULL;
    return newnode;
}

// 单链表打印
void SListPrint(SLNode* plist) {
    SLNode* cur = plist;
    while (cur != NULL) {
        printf("%d->", cur->data);
        cur = cur->next;
    }
    printf("NULL\n");
}

// 释放链表
void SListDestroy(SLNode** pphead) {
    SLNode* cur = *pphead;
    while (cur != NULL) {
        SLNode* next = cur->next;
        free(cur);
        cur = next;
    }
    *pphead = NULL;
}

// 单链表尾插
void SListPushBack(SLNode** pphead, SLTDateType x) {
    SLNode* newnode = BuySListNode(x);
    if (*pphead == NULL) {
        *pphead = newnode;
    } else {
        SLNode* tail = *pphead;
        while (tail->next != NULL) {
            tail = tail->next;
        }
        tail->next = newnode;
    }
}

// 单链表的尾删
void SListPopBack(SLNode** pphead) {
    assert(*pphead != NULL);
    if ((*pphead)->next == NULL) {
        free(*pphead);
        *pphead = NULL;
    } else {
        SLNode* tail = *pphead;
        while (tail->next->next != NULL) {
            tail = tail->next;
        }
        free(tail->next);
        tail->next = NULL;
    }
}

// 单链表的头插
void SListPushFront(SLNode** pphead, SLTDateType x) {
    SLNode* newnode = BuySListNode(x);
    newnode->next = *pphead;
    *pphead = newnode;
}

// 单链表头删
void SListPopFront(SLNode** pphead) {
    assert(*pphead != NULL);
    SLNode* temp = *pphead;
    *pphead = (*pphead)->next;
    free(temp);
}

// 单链表查找
SLNode* SListFind(SLNode* phead, SLTDateType x) {
    SLNode* cur = phead;
    while (cur != NULL && cur->data != x) {
        cur = cur->next;
    }
    return cur;
}

// 单链表在pos位置之后插入x
void SListInsertAfter(SLNode* pos, SLTDateType x) {
    assert(pos != NULL);
    SLNode* newnode = BuySListNode(x);
    newnode->next = pos->next;
    pos->next = newnode;
}

// 单链表在pos位置之后删除x
void SListEraseAfter(SLNode* pos) {
    assert(pos != NULL && pos->next != NULL);
    SLNode* toDelete = pos->next;
    pos->next = pos->next->next;
    free(toDelete);
}

// 单链表在pos位置插入x
void SListInsert(SLNode** pphead, SLNode* pos, SLTDateType x) {
    SLNode* newnode = BuySListNode(x);
    if (pos == *pphead) {
        SListPushFront(pphead, x);
    } else {
        SLNode* prev = *pphead;
        while (prev->next != pos) {
            prev = prev->next;
        }
        prev->next = newnode;
        newnode->next = pos;
    }
}

// 单链表删除pos位置的值
void SListErase(SLNode** pphead, SLNode* pos) {
    if (pos == *pphead) {
        SListPopFront(pphead);
    } else {
        SLNode* prev = *pphead;
        while (prev->next != pos) {
            prev = prev->next;
        }
        prev->next = pos->next;
        free(pos);
    }
}

最后,我们创建一个测试用例 main.c 来展示如何使用这些函数:

// main.c
#include <stdio.h>
#include "Slist.h"

int main() {
    SLNode* plist = NULL;

    // 尾部插入节点
    SListPushBack(&plist, 1);
    SListPushBack(&plist, 2);
    SListPushBack(&plist, 3);

    // 打印链表
    printf("Linked List after push back: ");
    SListPrint(plist);
    printf("\n");

    // 头部插入节点
    SListPushFront(&plist, 0);
    SListPushFront(&plist, -1);

    // 打印链表
    printf("Linked List after push front: ");
    SListPrint(plist);
    printf("\n");

    // 查找节点
    SLNode* found = SListFind(plist, 2);
    if (found) {
        printf("Found: %d\n", found->data);
    } else {
        printf("Not found\n");
    }

    // 尾部删除节点
    SListPopBack(&plist);

    // 打印链表
    printf("Linked List after pop back: ");
    SListPrint(plist);
    printf("\n");

    // 头部删除节点
    SListPopFront(&plist);

    // 打印链表
    printf("Linked List after pop front: ");
    SListPrint(plist);
    printf("\n");

    // 释放链表
    SListDestroy(&plist);

    return 0;
}

要运行这个程序,您需要将 Slist.h、Slist.c 和 main.c 保存到您的计算机上,然后使用C编译器编译它们。例如,如果您使用的是GCC编译器,可以通过以下命令编译程序:

gcc -o main Slist.c main.c
./main

原文链接

https://blog.csdn.net/qq_52158753/article/details/129858629

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值