C语言实现单链表

初步学习数据结构时,课通过C语言实现单链表的基本操作。如头插法与尾插法建立链表,链表的初始化、插入、删除与查找等。

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

#define headnote
//typedef struct LNode LNode;
/*定义一个单链表*/
typedef struct LNode {      //定义单链表结点类型
    int data;               //每个节点存放一个数据元素
    struct LNode* next;     //指针指向下一个节点
}LNode,*LinkList;
/*初始化单链表*/
bool InitList(LinkList *L) {
#ifndef headnote
    L = NULL;                    //空表,暂时还没有任何节点
#else
    (* L) = (LNode*)malloc(sizeof(LNode));//分配一个头结点
    if (L == NULL)                        //内存不足,分配失败
        return false;
    (*L)->next = NULL;                    //头结点后暂时还没有结点
#endif // !headnote

    return true;
}

/*判断单链表是否为空*/
bool Empty(LinkList L) {
#ifndef headnote
    return (L == NULL);
#else
    return (L->next == NULL);
#endif // !headnote
}

/*按位查找*/
LNode* GetElem(LinkList* L, int i) {
    if (i < 1)
        return NULL;
    LNode* p;                             //指针p指向当前扫描到的结点
    int j = 0;                           //当前p指向的是第几个结点
    p = (*L);                             //L指向头结点,头结点是第0个结点(不存数据

    while (p != NULL && j < i) {         //循环找到第i个结点
        p = p->next;
        j++;
    }
    return p;
}
/*按值查找*/
int LocateElem(LinkList* L, int i) {
    LNode* p=(*L)->next;                    //从第1个结点开始查找数据域为e的结点
    int j = 1;

    while (p != NULL && p->data!=i) {
        p = p->next;
        j++;
    }
    return j;
}

/*求表长*/
int Length(LinkList* L) {
    int len = 0;
    LNode* p = (*L);
    while (p->next != NULL) {
        p = p->next;
        len++;
    }
    return len;
}

/*指定节点的后插操作*/
bool InsertNextNode(LNode* p, int e) {
    if (p == NULL)
        return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));
    if (s == NULL) 
        return false;
    s->data = e;                    //用结点s保存数据元素s
    s->next = p->next;
    p->next = s;                    //将结点s连到p之后
    return true;
}
/*指定结点的前插操作*/
bool InsertPriorNode(LNode* p, int e) {
    if (p == NULL)
        return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));
    if (s == NULL)
        return false;
    s->next = p->next;
    p->next = s;                    //新结点s连到p之后
    s->data = p->data;              //将p中元素复制到s中
    p->data = e;                    //p中元素覆盖为e

    return true;
}
/*指定结点的删除*/
bool DeleteNote(LNode* p) {
    if (p == NULL)
        return false;
    LNode* q = p->next;              //令q指向*p的后继节点
    p->data = p->next->data;         //和后继节点交换数据域
    p->next = q->next;               //将*q结点从链中断开
    free(q);                         //释放后继结点的存储空间
    return true;
}

/*按位序插入*/
bool ListInsert(LinkList *L, int i, int e) {
    if (i < 1)
        return false;

#ifndef headnote
    if (i == 1) {            //插入第1个结点的操作与其他结点操作不同
        LNode* s = (LNode*)malloc(sizeof(LNode));
        s->data = e;
        s->next = (*L);
        (*L) = s;                //头指针指向新结点
        return true;
    }
#endif // !headnote

    LNode* p;                 //指针p指向当前扫描到的结点
    int j = 0;                //当前p指向的是第几个结点
    p = (*L);                    //L指向头结点,头结点是第0结点(不存数据)

    while (p != NULL && j < i - 1) {//循环找到第i-1个结点
        p = p->next;
        j++;
    }
    InsertNextNode(p, e);
    return true;
}
/*按位序删除*/
bool ListDelete(LinkList *L, int i, int* e) {
    if (i < 1)
        return false;
    LNode* p;
    int j = 0;
    p = (*L);

    while (p != NULL && j < i - 1) { 
        p = p->next;
        j++;
    }

    if (p == NULL)
        return false;
    if (p->next == NULL)                  //第i-1个结点之后已无其他结点
        return false;
    LNode* q = p->next;                   //令q指向被删除结点
    *e = q->data;                          //用e返回元素的值
    p->next = q->next;                    //将*q结点从链中断开
    free(q);                              //释放结点的存储空间
    return true;                          //删除成功
}

/*尾插法建立单链表*/
LinkList List_TailInsert(LinkList* L) {    //正向建立单链表
    int x;                                 //设ElemType为整型
    (*L) = (LinkList)malloc(sizeof(LNode));    //建立头结点
    LNode* s, * r = (*L);                     //r为表尾指针
    scanf_s("%d", &x);                       //输入结点的值
    while (x != 9999) {                    //输入9999表示结束
        s= (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        r = s;                             //r指向新的表尾结点
        scanf_s("%d", &x);
    }
    r->next = NULL;                        //尾结点指针为空
    return (*L);
}
/*头插法建立单链表*/
LinkList List_HeadInsert(LinkList* L) {    //逆向建立单链表
    LNode* s;
    int x;
    (*L) = (LinkList)malloc(sizeof(LNode));   //建立头结点
    (*L)->next = NULL;                        //初始为空表

    scanf_s("%d", &x);
    while (x != 9999) { 
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        s->next = (*L)->next;
        (*L)->next = s;
        scanf_s("%d", &x);
    }
    return (*L);
}

void main() {
    LinkList L;                 //声明一个指向单链表的指针
    InitList(&L);               //初始化一个空表

    ListInsert(&L,1,11);        //11
    InsertNextNode(L->next, 13);//11,13
    InsertPriorNode(L->next->next, 12);//11,12,13
    printf("此时该单链表的表长为%d\n",  Length(&L));
    int i = 2;
    printf("第%d位数据为%d\n", i, (GetElem(&L,i))->data);
    i = 12;
    printf("数据为%d的结点在第%d位\n", i, LocateElem(&L, i));

    int e = -1;
    ListDelete(&L, 2, &e);//11,13
    DeleteNote(L->next);//13
}

过程中遇到的问题:

  1. "->next"的左侧必须指向结构/联合

解决办法:

->操作符优先级高于*操作符优先级,把L->next换成(*L)->next即可

  1. 'scanf':this function or variable may be unsafe.Consider using scanf_s instead

解决方法:

将scanf替换为提示中的scanf_s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值