链表基本操作的实现(C语言)

本文详细介绍了链表的基本操作,包括单链表的创建(头插法与尾插法)、查找、插入和删除结点等,并探讨了循环链表和双向链表的特性。通过C语言代码实现,讲解了链表数据结构的应用和操作技巧。


一些关于链表的学习笔记

单链表(又称线性链表)

单链表的定义与声明

  • 储存结构特点:用一组任意的储存单元储存线性的数据元素(储存单元可以是线性或非线性)。链表的每个结点,除存放元素信息外还需要存放一个指向其直接后继的指针。

  • 优点:比起顺序表需要大量的连续的储存单元,单链表的储存单元可以是任意的

  • 缺点:

    1. 需要多余的空间存放指针域。
    2. 查找某个特定结点时需要通过遍历查找。
  • 代码实现:

typedef int ElemType;	
/*在数据结构中使用ElemType代表任意数据类型,
为了可以直接粘贴后运行,在这里使用int类型做演示*/
typedef struct LNode{
   
   
    ElemType data;	//用于记录结点中的数据
    struct LNode *next;	//指向下一个结点的指针
}LNode,*LinkList;	//声明类型LNode与其指针*LinkList
  • 上述之所以声明两个定义是为了好对结点和链表加以区分
    • LNode * 等价于 LinkList
    • LNode *:代表指向某一个结点的指针
    • LinkList:代表指向单链表中第一个结点的指针。

单链表的创建

  • 为了使空链表与非空链表的处理操作一致,以下全部采用带头结点的方式创建

头插法创建单链表

//使用头插法创建单链表
LinkList creat_LinkList_HeadInsert(void){
   
   
    ElemType data;  //创建结点时输入的数据
    LinkList L;
    LNode *p;   //p指向当前结点
    L = (LNode *)malloc(sizeof(LNode));  //创建头结点
    L->next = NULL; //初始化头结点,指向NULL
    
    printf("开始使用头插法创建单链表。。。\n");
    while (1) {
   
   
        printf("请输入插入的数据数据:");
        scanf("%d",&data);
        if(data==9999)  break;  //输入结果为9999时停止创建
        p = (LNode *)malloc(sizeof(LNode));  //创建新结点
        p->data = data;		//将输入的元素赋值给新结点中的数据元素
        p->next = L->next;	//
        L->next = p;    //新创建的结果总是作为第一个结点
    }
    
    return L;
}
  • 时间复杂度:
    • 每个结点插入的时间复杂度为O(1)
    • 设单链表长为n,则总时间复杂度为O(n)
  • 优点:算法实现简单
  • 缺点:生成的链表中结点的次序与输入次序不同,可以使用此特点进行链表反转

尾插法创建单链表

//使用尾插法创建单链表
LinkList creat_LinkList_RearInsert(void){
   
   
    ElemType data;  //创建结点时输入的数据
    LinkList L;     //指向头结点
    LNode *p,*r;    //p指向当前结点,r指向尾部结点
    L = r = (LNode *)malloc(sizeof(ElemType)); //使链表L与尾结点r都指向头结点
    L->next = NULL;
    
    printf("开始使用尾插法创建单链表。。。\n");
    while (1) {
   
   
        printf("请输入插入的数据数据:");
        scanf("%d",&data);
        if(data==9999)  break;
        p = (LNode *)malloc(sizeof(LNode));
        p->data = data;
        p->next = r->next;
        r->next = p;
        r = p;      //新创建的结点总是作为最后一个结点
    }
    
    return L;
}
  • 头插法与尾插法主要的区别就在于:
    • 头插法会将新结点(*p)赋值给头结点(L)的指针域(*next);
    • 尾插法会将新结点(*p)赋值给尾结点(*r)的指针域(*next),并让指向尾结点的指针指向新结点。

查找结点操作

  • 由于链表本身特点的原因,只能从头结点开始依次遍历查找,因此为顺序存取结构而非随机存取结构

按序号查找结点值

//按位置获取数据
LNode * GetElem(LinkList L, int i){
   
   
    LNode *p = L;   //用于指向当前节点,此时为头结点
    int j = 0;  //用于记录当前节点的位置,此时为头结点
    if (i<0) {
   
     //i取值不合法
        return NULL;
    }
    
    while (p!=NULL 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值