数据结构——单链表的实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构——单链表的实现相关的知识,希望对你有一定的参考价值。

简单实现了单链表的功能,在查找、求前驱、插入、删除方法中判断了越界问题,并没有考虑其他可能产生的错误。

/*
    单链表:用一组地址任意的存储单元存放线性表中的数据元素
    结点(数据元素) = 元素(数据元素的映像) +    指针(指示后继元素的位置)
    以“结点的序列”表示线性表——单链表。
*/

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

//定义数据类型
typedef int ElemType;

//单链表的存储结构
typedef struct LNode{
    ElemType data;    //数据域
    struct LNode *next;    //指针域
}LNode, *LinkList;

//声明,指针函数
void(*visit)(LNode *node);

//声明,辅助函数
void visitData(LNode *node);

//线性表带有头结点,因此第一个结点有前驱,即为头结点
//对单链表的基本操作
void CreateList(LinkList &L);    //创建线性表,从后往前建表
LinkList GetLNode(LinkList L, int i);    //返回第i个结点
LinkList GetFirst(LinkList L);    //返回第一个结点
LinkList PriorLNode(LinkList L, int i);    //返回第i结点的前驱结点
void ListTraverse(LinkList L, void(visit(LNode *node)));    //遍历单链表
void ListInsert(LinkList &L, int i, ElemType e);    //在第i个结点之前插入,数据域是e的结点
void AppendFirst(LinkList &L, ElemType e);    //在第一个结点之前插入,数据域是e的结点
void AppendLast(LinkList &L, ElemType e);    //在最后一个结点之后插入,数据域是e的结点
void ListDelete(LinkList &L, int i, LinkList &rNode);    //删除第i个结点并返回
void DeleteFirst(LinkList &L, LinkList &rNode);    //删除第一个结点并返回
void DeleteLast(LinkList &L, LinkList &rNode);    //删除最后一个结点并返回

//测试模块
int main(){
    LinkList L;
    printf("请创建单链表:");
    CreateList(L);
    ListTraverse(L, visitData);
    printf("\n");


    //获取第一个结点,最后一个结点(人为设置表长的),不存在的结点
    printf("第一个结点的值:%d\n", GetFirst(L)->data);
    printf("最后一个结点的值:%d\n", GetLNode(L, 6)->data);
    printf("索引小于1结点的值:%d\n", GetLNode(L, 0)->data);
    printf("索引大于表长结点的值:%d\n\n", GetLNode(L, 7)->data);

    //获取第一个结点,最后一个结点,不存在的结点的的前驱
    printf("第一个结点的前驱的值:%d\n", PriorLNode(L, 1)->data);
    printf("最后一个结点的前驱的值:%d\n", PriorLNode(L, 6)->data);
    printf("索引小于1结点:%s\n", PriorLNode(L,0));
    printf("索引大于表长结点:%s\n\n", PriorLNode(L, 7));

    //在第一个结点之前插入,在最后一个结点之前插入
    AppendFirst(L, 7);
    AppendLast(L, 0);
    ListTraverse(L, visitData);
    ListInsert(L, 3, 8);
    ListTraverse(L, visitData);
    printf("\n");

    LNode *rNode;
    //删除任意结点,删除第一个结点,删除最后一个结点
    ListDelete(L, 3, rNode);
    ListTraverse(L, visitData);
    DeleteFirst(L, rNode);
    DeleteLast(L, rNode);
    ListTraverse(L, visitData);

    system("pause");
    return 0;
}

//各函数定义模块
void visitData(LNode *node){
    printf("%4d", node->data);
}

void CreateList(LinkList &L){    //创建线性表,从后往前建表
    L = (LinkList)malloc(sizeof(LNode));
    if (!L)
        return;
    L->next = NULL;

    ElemType elem;

    scanf_s("%d", &elem);
    while (elem != -1){
        LNode *newNode = (LinkList)malloc(sizeof(LNode));
        if (!newNode)
            return;
        newNode->data = elem;
        newNode->next = L->next;
        L->next = newNode;
        scanf_s("%d", &elem);
    }
}

LinkList GetLNode(LinkList L, int i){    //返回第i个结点的值
    int j = 1;
    LNode *p = L->next;

    //找第i个结点
    while (p && j != i){
        p = p->next;
        j++;
    }

    if (j > i || !p){
        printf("\n不存在该结点!\n");
        return L;
    }

    return p;
}

LinkList GetFirst(LinkList L){    //返回第一个结点的值
    return GetLNode(L, 1);
}

LinkList PriorLNode(LinkList L, int i){    //返回第i结点的前驱结点
    int j = 1;
    LNode *p = L;

    //找第i-1个结点,而且第i个结点不为空
    while (p->next && j != i){
        p = p->next;
        j++;
    }

    if (j > i || !p->next){
        printf("\n在链表中不存在该结点,没有前驱!\n");
        return NULL;
    }

    return p;
}

void ListTraverse(LinkList L, void(visit(LNode *node))){    //遍历单链表
    LNode *p = L->next;
    while (p){
        visit(p);
        p = p->next;
    }
    printf("\n");
}

void ListInsert(LinkList &L, int i, ElemType e){    //在第i个结点之前插入,数据域是e的结点
    LNode *p = PriorLNode(L, i);
    LNode *newNode = (LinkList)malloc(sizeof(LNode));
    if (!newNode)
        return;
    newNode->data = e;

    newNode->next = p->next;
    p->next = newNode;
}

void AppendFirst(LinkList &L, ElemType e){    //在第一个结点之前插入,数据域是e的结点
    ListInsert(L, 1, e);
}

void AppendLast(LinkList &L, ElemType e){    //在最后一个结点之后插入,数据域是e的结点
    //找到最后一个结点
    LNode *p = L;
    while (p->next){
        p = p->next;
    }
    //新建一个结点
    LNode *newNode = (LinkList)malloc(sizeof(LNode));
    if (!newNode)
        return;
    newNode->data = e;
    //插入
    newNode->next = p->next;
    p->next = newNode;
}

void ListDelete(LinkList &L, int i, LinkList &rNode){    //删除第i个结点并返回
    LNode *p = PriorLNode(L, i);
    LNode *q = p->next;
    rNode = q;
    p->next = q->next;
    free(q);
}

void DeleteFirst(LinkList &L, LinkList &rNode){    //删除第一个结点并返回
    ListDelete(L, 1, rNode);
}

void DeleteLast(LinkList &L, LinkList &rNode){    //删除最后一个结点并返回
    //找到最后一个结点的前驱
    LNode *p = L;
    while (p->next->next){
        p = p->next;
    }
    LNode *q = p->next;
    rNode = q;
    free(q);
    p->next = NULL;
}

不积跬步,无以至千里;不积小流,无以成江海。坚持着。

以上是关于数据结构——单链表的实现的主要内容,如果未能解决你的问题,请参考以下文章

C数据结构单链表接口函数逻辑解析与代码实现(含详细代码注释)

数据结构初阶第三篇——单链表(实现+动图演示)[建议收藏]

数据结构代码(用C语言) 单链表的插入和删除

数据结构-编程实现一个单链表的打印

数据结构之单链表的增删查改等操作画图详解

单链表的基本实现