C语言单链表及基本操作的实现

        数据结构中,单向链表(又名单链表、线性链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过从头部开始,依序往下读取。

        下面的代码是使用指针实现的一个单链表,称为动态单链表;当然,也可以使用数组实现一个单链表,为静态单链表,后面学习之后,再用数组实现单链表。

完整代码如下:

一、定义头文件:list.h

#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED
struct Node;
typedef struct Node *PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;

List MakeEmpty(List L);     //生成空链表L

void DestroyList(List L);   //销毁链表L

_Bool IsEmpty(List L);        //判定链表是否为空

_Bool IsLast(Position P, List L);   //判定位置P的节点是否为尾结点

int Length(List L);  //查看链表长度

Position Find(int X, List L); //在链表L中查找数据项为X的第一个结点

void Delete(int X, List L); //在链表L中删除数据项为X的第一个结点

Position FindPrevious(int X, List L); //在链表L中查找数据项为X的第一个结点的前驱位置

Position FindNext(int X,List L); //在链表L中查找数据项为X的第一个结点的后继位置

void Insert(int X, List L, Position P); //在链表L中P位置插入数据项为X的结点

void DeleteList(List L); //删除链表L头结点外的所有结点

Position Header(List L);  //获得链表L中头结点位置

Position First(List L);   //获得链表L中第一个数据结点的位置

Position Advance(Position P); //获得P位置的后继结点位置

int Retrieve(Position P); //获取P位置结点的数据项

struct Node
{
    int data;
    Position next;
};

#endif // LIST_H_INCLUDED

二、各个函数的实现: list.c

#include "list.h"
#include <malloc.h>
#include <stdlib.h>
#include<stdio.h>

/*初始化:创建一个空的单链表*/
List MakeEmpty(List L)
{
    L = (PtrToNode)malloc(sizeof(PtrToNode));  //创建一个头结点
    if(!L)
    {
        printf("申请空间失败!\n");
        exit(0);
    }
    L->data = 0; //无效值,不赋值的话就是随机值
    L->next = NULL;
    return L;
}

/*销毁链表L*/
void DestroyList(List L)
{
    Position P, Temp;
    P = L;
    while(P->next != NULL)
    {
        Temp = P->next;
        free(P);
        P = Temp;
    }
}

/*测试空表*/
_Bool IsEmpty(List L)
{
    return L->next == NULL; //Return ture if L is empty
}

/*测试是否为尾节点*/
_Bool IsLast(Position P, List L)
{
    return P->next == NULL; //Return ture if P is the last position in List L
}

/*返回链表长度*/
int Length(List L)
{
    int length = 0;
    Position P;
    P = L->next;
    while(P)
    {
        length++;
        P = P->next;
    }
    return length;
}

/*查找给定元素在表中的位置*/
Position Find(int X, List L)
{
    Position P;
    P = L->next;
    while(P != NULL && P->data != X)
    {
        P = P->next;
    }
    return P;   //Return Position of X in L; NULL if not found
}

/*删除表中某个元素X*/
void Delete(int X, List L)
{
    Position P, Temp;
    P = FindPrevious(X, L); //首先找到该元素的先前节点
    if(!IsLast(P, L))
    {
        Temp = P->next;     //此时Temp即是X所在结点
        P->next = Temp->next;
        free(Temp);
    }
}

/*查找表元X的前驱*/
Position FindPrevious(int X, List L)
{
    Position P;
    P = L;
    while(P->next != NULL && P->next->data != X)
    {
        P = P->next;
    }
    return P;
}

/*查找表元X的后继*/
Position FindNext(int X,List L)
{
    Position P;
    P = L;
    while(P != NULL && P->data != X) //当P->next == X 时,说明此事P结点即为X所在元素的结点
    {
        P = P->next;
    }
    P = P->next; //此时P即为X所在结点位置,P重新赋值为P的下一个即后继结点
    return P;
}

/*向表L中P位置之后插入元素*/
void Insert(int X, List L, Position P)
{
    Position Temp;
    Temp = malloc(sizeof(struct Node));
    if(Temp == NULL)
    {
        printf("申请空间失败!\n");
        exit(0);
    }
    Temp->data = X;
    Temp->next = P->next;
    P->next = Temp;
}

/*清空链表L*/
void DeleteList(List L)
{
    Position P, Temp;
    P = L->next;    //P此时为头结点
    while(P != NULL)    //从头结点开始,从前往后,依次释放每一个结点,清除
    {
        Temp = P->next;
        free(P);
        P = Temp;
    }
    L->next = NULL; //保留头结点
}

/*获取位置P后继结点的位置*/
Position Advance(Position P)
{
    if(P != NULL)
    {
        P = P->next;
    }
    return P;
}

/*获取位置为P的结点的数据项*/
int Retrieve(Position P)
{
    if(P != NULL)
        return P->data;
    else
        return 0;
}

/*获取链表L第一个结点的位置*/
Position First(List L)
{
    if(L->next != NULL)
        return L->next;
    else
        return L; //为空就返回头结点位置
}

/*获取链表L头结点位置*/
Position Header(List L)
{
    return L;
}

三、main函数测试 : Main.c

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

int main(void)
{
    List list = NULL, p;
    int i;
    list = MakeEmpty(list);

    if(IsEmpty(list))
        printf("空表!\n");
    else
        printf("非空!\n");

    p = list;
    for(i=0; i<5; i++)
    {
        Insert(i*5, list, p);
        p = Advance(p);
        printf("已插入值为%d的新节点\n", i*5);
    }

    printf("链表长度为%d\n", Length(list));

    p = FindNext(5, list);
    printf("数据项为5的结点的后继结点数据项为%d \n", Retrieve(p));

    Delete(10, list);

    p = FindNext(5, list);
    printf("数据项为5的结点的后继结点数据项为%d \n", Retrieve(p));

    p = First(list);
    printf("第一个结点数据项为%d\n", Retrieve(p));

    printf("头结点位置为%p\n", Header(list));

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38762390/article/details/84973815