• 数据结构与算法分析-用C语言实现单链表


    掌握单链表很容易,把下面的代码弄懂,敲几遍,全部记住,而且记清每一个细节。

    首先,在List.h中声明单链表的ADT.我们把我们所需要的自定义类型啊,函数啊,都声明出来,但这里我们只是声明他们,而具体实现则是在List.c中进行。

    /**
    * @file    List.h
    * @brief   单链表的声明
    * @details
    * @author   mrbourne@163.com
    * @date     2014-5-19
    */
    #ifndef _List_H
    
    //先声明实现单链表时所需的类型和结构,包括一个节点结构体,元素类型,指向元素的指针类型(同样可以用来表示单链表本身和元素位置)
    struct Node;
    typedef int ElementType;    //此处根据链表中元素类型的不同 可以修改
    typedef struct Node *PtrToNode;
    typedef PtrToNode List;
    typedef PtrToNode Position;
    
    //接下来声明一些常用的函数,一定要记住这些函数,因为这些函数都是最常用最基础的
    List MakeEmpty(List L); //置空链表
    int IsEmpty(List L);    //判空链表
    int IsLast(Position P,List L);  //判断是否为表尾
    Position Find(ElementType X,List L);    //找出元素所在位置
    void Delete(ElementType X,List L);      //删除元素
    Position FindPrevious(ElementType X,List L);    //找到某元素的前驱
    void Insert(ElementType X,List L,Position P);   //插入一个元素
    void DeleteList(List L);    //删除链表
    Position Header(List L);    //返回头结点
    Position First(List L);     //返回第一个元素
    Position Advance(Position P);   //返回后一个位置
    ElementType Retrieve(Position P);   //获取位置P处的元素值
    
    #endif // _List_H
    

    声明完了以后,我们就要逐步实现这些单链表的ADT,实现的代码放在List.c中

    具体实现代码如下:

    /**
    * @file    List.h
    * @brief   链表的实现部分
    * @details
    * @author   mrbourne@163.com
    * @date     2014-5-19
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <List.h>	//别忘了先把声明部分的头文件List.h包含进来
    
    //实现节点结构体
    struct Node
    {
        ElementType Element;	//元素
        Position    Next;		//指向下个元素的指针
    };
    
    //空链表返回true
    int IsEmpty(List L)
    {
        return L->Next == NULL;
    }
    
    //当前位置是否为链表末尾
    int IsLast(Position P, List L)
    {
        return P->Next == NULL;
    }
    
    //找到一个元素所在的位置
    Position Find(ElementType X, List L)
    {
        Position P;
        P = L->Next;    //P初始化为a1
        while(P != NULL && P->Element != X)		//只要没到表尾,且当前节点中的元素不等于所给参数,就一直向后遍历
            P = P->Next;
        return P;
    }
    //找到某个元素的前驱
    Position FindPrevious(ElementType X, List L)
    {
        Position P;
        while(P->Next != NULL && P->Next->Element != X)	//下一个元素没到表尾,且下一个元素不匹配,则继续遍历
            P = P->Next;
        return P;
    }
    
    //删除某个元素x
    void Delete(ElementType X, List L)
    {
        Position P,TmpCell; //前驱和当前节点
        P = FindPrevious(X,L);
        if(!IsLast(P,L))    //成功找到了该元素的前驱,若IsLast成立,则表示没有找到前驱
        {
            TmpCell = P->Next;	
            P->Next = TmpCell->Next;
            free(TmpCell);
        }
    }
    
    //打印错误信息
    void FatalError(char *str)
    {
        printf("%s
    ", str);
    }
    
    //在某个元素前插入一个元素
    void Insert(ElementType X, List L, Position P)
    {
        Position NewCell;
        NewCell = malloc(sizeof(struct Node));  //申请空间
        if(NewCell == NULL)
            FatalError("Out of space!!!");
    
        NewCell->Element = X;
        NewCell->Next = P->Next;
        P->Next = NewCell;
    }
    
    //删除一个链表
    void DeleteList(List L)
    {
        Position P,Tmp;
        P = L->Next;
        L->Next = NULL; //释放头结点
        while(P != NULL)    //需要用Tmp保存当前节点 因为在free(P)后 不能再对P引用进行P = P->Next
        {
            Tmp = P->Next;
            free(P);
            P = Tmp;
        }
    
    }
    

    至此,我们已经基本实现一个单链表和其基础的操作。这里有几个例程并没有实现,不要着急,这里的单链表还不能供我们使用,有几个历程和后面我们实现栈和队列时大同小异,等学完栈和队列,我们再回来把剩下的几个例程补上,然后也像测试栈和队列一样,在主程序中来测试一下单链表。



  • 相关阅读:
    《测试工作量的时间评估》方案梳理
    GitHub 生成密钥
    Jenkins+Jmeter持续集成(五、Ant+GitLab持续构建)
    Linux下查看文件和文件夹大小
    Java Runtime.exec()的使用
    如何启动/停止/重启MySQL
    浅析Java语言慢的原因
    chattr命令锁定账户敏感文件
    SOAP协议初级指南 (三)
    SOAP协议初级指南 (二)
  • 原文地址:https://www.cnblogs.com/mrbourne/p/9959462.html
Copyright © 2020-2023  润新知