数据结构——线性表的单链表存储(优缺点及代码实现:C语言)

链式存储

优点:不要求大片连续空间,改变容量方便
缺点:不可随机存取,要耗费一定空间存放指针

两部分组成(数据域 + 指针域)
逻辑上相邻的数据元素在物理上不一定相邻
访问只能通过头指针进入链表 并通过每个元素指针域顺序查找其他元素节点(顺序存取法)

综上:该存储方式适合频繁插入删除 场景,不适合频繁查找访问数据

代码实现(C语言)

定义链表

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

// 定义链表节点数据类型
typedef int DataType;

// 定义链表节点结构
typedef struct Node
{
   
   
    DataType data;
    struct Node *next;
} LinkNode, *LinkList;   //这两个都是结构体的别名,
//LinkNode *p 代表定义一个指针类型的节点p(强调节点),也可以表示为 LinkList p;(强调是一个单链表),为了可读性

初始化

LinkList InitList()
{
   
   
    LinkList L;				
    L = (LinkNode *)malloc(sizeof(LinkNode));    //内存分配节点  c++ 是 L=new LinkNode;
    if (L == NULL)
    {
   
   
        printf("内存分配失败");
        exit(1);
    }
    L->next = NULL;
    return L;
}

使用头插法建立单链表

时间复杂度O(n)
头插法是逆序插入,在头节点后,次新节点前插入新节点

void CreateList_H(LinkList L, int n)		//n代表节点数
{
   
   
	int i;					//当前节点序号
    LinkNode *s;
    for (i = 0; i < n; i++)            //循环建立、插入 n个节点
    {
   
   
        s = (LinkNode *)malloc(sizeof(LinkNode));
        if (s == NULL)
        {
   
   
            printf("内存分配失败");
            exit(1);
        }
        printf("请输入第 %d 个元素值: ", i + 1);    //节点序号是从0开始的
        scanf("%d", &s->data);    //输入的值传给节点的data域
        s->next = L->next;		  //节点插入在头指针的下一个,也就是其他节点之前
        L->next = s;			  //连接起来	
    }
}

尾插法建立单链表

时间复杂度O(n)
顺序插入,定义一个尾指针,循环在尾指针的下一个插入新节点,最后再将最后一个节点的next域设空。

void CreateList_R(LinkList L, int n)
{
   
   
    LinkNode *s, *r;  //s是新节点的指针,r是尾指针
	int i;
    r = L;
    for (i = 0; i < n; i++)   //循环建立、插入 n个节点
    {
   
   
        s = (LinkNode *)malloc(sizeof(LinkNode));
        if (s == NULL)
        {
   
   
            printf("内存分配失败");
            exit(1);
        }
        printf("请输入第 %d 个元素值: ", i + 1);  
        scanf("%d", &s->data);  
        r->next = s;  //在最后一个节点后面插入新节点s
        r = s;		//尾指针r移动到 新插入的节点s处
    }
    r->next = NULL;		//循环结束后最后一个节点的next域指向空
}

ps:如果不懂头插法和尾插法如何实现的可以看下这个博主画的动图,很生动形象:
链接: 单链表之头插法和尾插法(动图+图解)

单链表判空

int IsEmpty(LinkList L)
{
   
   
	return L->next ==NULL;  //若为真返回1 表示空表,为假返回0
}

获取表长

定义一个计数器,遍历一遍链表,计数器++;
时间复杂度O(n)

int GetLength(LinkList L)
{
   
   
	int length = 0;
	LinkNode *p = L->next;  //定义一个指针指向第一个节点
	while(p)            //与while(p!= NULL)等价
	{
   
   
		length++;
		p = p->next;  
	}
	return length;   //返回表长
}

按值查找

循环链表,从第一个元素向后一个个进行值的比对
时间复杂度O(n)

int SearchByValue(LinkList L, DataType key)
{
   
   
    int index = 1;
    LinkNode *p = L->next;
    while (p)		//与while(p!= NULL)等价
    {
   
   
        if (p->data == key)
        {
   
   
            return index;
        }
        p = p->next;
        index++;
    }
    return 0;    //如果没找到与key相匹配的元素 返回0
}

按位查找

时间复杂度O(n)
建一个计数器,遍历链表,计数器++直到和位置相等。最后返回查找元素的值

DataType <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值