线性表---单链表的实现

单链表详解

引言

单链表是一种基本的数据结构,广泛应用于各种编程场景中。它是由一系列节点组成的数据结构,每个节点包含数据部分和指向下一个节点的指针。单链表的优点在于它能够灵活地插入和删除节点,而不必像数组那样移动大量元素。

单链表的定义

节点结构

单链表中的每个节点通常由两部分组成:

  1. 数据部分:存储实际的数据项。
  2. 指针部分:存储指向下一个节点的地址。

节点的结构可以用 C 语言定义如下:

typedef struct ListNode {
    int data;        // 存储数据
    struct ListNode *next;  // 指向下一个节点的指针
} ListNode;

链表结构

单链表由一个头结点和一系列普通节点组成。头结点通常不存储数据,而是作为一个指向第一个数据节点的指针。

链表的结构可以用 C 语言定义如下:

ListNode *head;  // 头结点

单链表的基本操作

初始化

初始化一个空的单链表包括分配一个头结点,并将其 next 指针设置为 NULL

bool InitList(ListNode *&head) {
    head = (ListNode *)malloc(sizeof(ListNode));
    if (head == NULL) {
        return false;  // 内存分配失败
    }
    head->next = NULL;
    return true;
}

插入

插入操作可以发生在链表的任何位置,常见的有头部插入和尾部插入。

头部插入
void ListHeadInsert(ListNode *&head) {
    int x;
    ListNode *s;
    printf("请输入加入单链表的值(输入-1结束):");
    scanf("%d", &x);
    while (x != -1) {
        s = (ListNode *)malloc(sizeof(ListNode));
        s->data = x;
        s->next = head->next;
        head->next = s;
        scanf("%d", &x);
    }
}
尾部插入
void ListTailInsert(ListNode *&head) {
    int x;
    ListNode *s, *r = head;
    printf("请输入加入单链表的值(输入-1结束):");
    scanf("%d", &x);
    while (x != -1) {
        s = (ListNode *)malloc(sizeof(ListNode));
        s->data = x;
        s->next = NULL;
        r->next = s;
        r = s;
        scanf("%d", &x);
    }
}

删除

删除操作可以从链表中移除一个节点。通常需要找到待删除节点的前一个节点。

bool ListDelete(ListNode *&head, int i, int &e) {
    int j = 0;
    ListNode *p = head, *q;
    if (i <= 0) {
        return false;
    }
    while (j < i - 1 && p != NULL) {
        j++;
        p = p->next;
    }
    if (p == NULL || p->next == NULL) {
        return false;
    }
    q = p->next;
    e = q->data;
    p->next = q->next;
    free(q);
    return true;
}

查询

查询操作可以查找特定值或位置上的节点。

按值查询
int LocateElem(ListNode *head, int e) {
    int i = 1;
    ListNode *p = head->next;
    while (p != NULL && p->data != e) {
        p = p->next;
        i++;
    }
    if (p == NULL) {
        return 0;
    } else {
        return i;
    }
}
按位置查询
int GetElem(ListNode *head, int i) {
    int j = 0;
    ListNode *p = head;
    if (i <= 0) {
        return -1;
    }
    while (j < i && p != NULL) {
        j++;
        p = p->next;
    }
    if (p == NULL) {
        return -1;
    } else {
        return p->data;
    }
}

打印输出

输出链表中的所有节点。

void DisplayList(ListNode *head) {
    ListNode *p = head->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

销毁

销毁整个链表。

void DestroyList(ListNode *&head) {
    ListNode *p = head->next, *q;
    while (p != NULL) {
        q = p;
        p = p->next;
        free(q);
    }
    free(head);
}

示例程序

下面是一个使用上述定义和操作的完整单链表程序示例:

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

typedef struct ListNode {
    int data;
    struct ListNode *next;
} ListNode;

bool InitList(ListNode *&head) {
    head = (ListNode *)malloc(sizeof(ListNode));
    if (head == NULL) {
        return false;
    }
    head->next = NULL;
    return true;
}

void ListHeadInsert(ListNode *&head) {
    int x;
    ListNode *s;
    printf("请输入加入单链表的值(输入-1结束):");
    scanf("%d", &x);
    while (x != -1) {
        s = (ListNode *)malloc(sizeof(ListNode));
        s->data = x;
        s->next = head->next;
        head->next = s;
        scanf("%d", &x);
    }
}

void ListTailInsert(ListNode *&head) {
    int x;
    ListNode *s, *r = head;
    printf("请输入加入单链表的值(输入-1结束):");
    scanf("%d", &x);
    while (x != -1) {
        s = (ListNode *)malloc(sizeof(ListNode));
        s->data = x;
        s->next = NULL;
        r->next = s;
        r = s;
        scanf("%d", &x);
    }
}

bool ListDelete(ListNode *&head, int i, int &e) {
    int j = 0;
    ListNode *p = head, *q;
    if (i <= 0) {
        return false;
    }
    while (j < i - 1 && p != NULL) {
        j++;
        p = p->next;
    }
    if (p == NULL || p->next == NULL) {
        return false;
    }
    q = p->next;
    e = q->data;
    p->next = q->next;
    free(q);
    return true;
}

int LocateElem(ListNode *head, int e) {
    int i = 1;
    ListNode *p = head->next;
    while (p != NULL && p->data != e) {
        p = p->next;
        i++;
    }
    if (p == NULL) {
        return 0;
    } else {
        return i;
    }
}

int GetElem(ListNode *head, int i) {
    int j = 0;
    ListNode *p = head;
    if (i <= 0) {
        return -1;
    }
    while (j < i && p != NULL) {
        j++;
        p = p->next;
    }
    if (p == NULL) {
        return -1;
    } else {
        return p->data;
    }
}

void DisplayList(ListNode *head) {
    ListNode *p = head->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

void DestroyList(ListNode *&head) {
    ListNode *p = head->next, *q;
    while (p != NULL) {
        q = p;
        p = p->next;
        free(q);
    }
    free(head);
}

int main() {
    ListNode *head;
    bool flagInsert = true;
    if (InitList(head)) {
        printf("单链表已初始化。\n");
    }

    ListHeadInsert(head);
    printf("插入数据结束\n");
    DisplayList(head);

    bool flagDelete = true;
    while (flagDelete) {
        int i;
        int e;
        printf("请输入需要删除的位置(输入0退出):");
        scanf("%d", &i);
        if (i == 0) {
            break;
        }
        flagDelete = ListDelete(head, i, e);
        if (flagDelete) {
            printf("删除数据成功,删除的数据为%d\n", e);
            DisplayList(head);
        } else {
            printf("删除数据失败\n");
        }
    }
    printf("删除数据结束\n");

    int value;
    printf("请输入需要按值查询的值:");
    scanf("%d", &value);
    int position = LocateElem(head, value);
    if (position > 0) {
        printf("查询成功,查询到的值为:%d\n", value);
    } else {
        printf("查询失败\n");
    }

    int wei;
    printf("请输入需要按位查询的位置:");
    scanf("%d", &wei);
    int zhi = GetElem(head, wei);
    if (zhi != -1) {
        printf("查询成功,查询到的值为:%d\n", zhi);
    } else {
        printf("查询失败\n");
    }

    DestroyList(head);
    printf("销毁单链表\n");

    return 0;
}

以上就是单链表的详细介绍。希望这份文档能帮助您更好地理解和使用单链表。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值