单链表头插法和尾插法建表-C语言实现

本文介绍了一种使用C语言实现单链表的方法,包括头插法和尾插法,并提供了完整的代码示例。通过这两种方法可以有效地创建单链表结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define FALSE 0
#define ERROR 0
#define TRUE 1
typedef int ElemType;
typedef int Status;
typedef struct Node
{
ElemType Data;
struct Node *next;
}List;
//输出链表//
void ShowList(List *Ptrl)
{
//p指针指向该结点
List *p= Ptrl;
//从该结点开始输出数据域
p=p->next;
while(p)
{
printf("%d ",p->Data);
p=p->next;
}
printf("\n");
}
//单链表头插法
List* Insert_Head(List *Ptrl)
{
//头指针指向头结点
List *p=Ptrl;
List *s;
int i;
p=(List*)malloc(sizeof(List));
p->next=NULL;
printf("请输入数据,以1000结束\n");
scanf("%d",&i);
while(i!=1000)
{
//分配空间
s=(List*)malloc(sizeof(List));
//赋值,链接
s->Data = i;
s->next = p->next;
p->next = s;
scanf("%d",&i);
}
return p;
}
//单链表尾插法
List* Insert_Tail(List *Ptrl)
{
List *p=Ptrl;
//尾指针
List *r;
//当前指
List *s;
int i;
p=(List*)malloc(sizeof(List));
p->next=NULL;
r=p;
    printf("请输入数据,以1000结束\n");
scanf("%d",&i);
while(i!=1000)
{
s=(List*)malloc(sizeof(List));
s->Data=i;
s->next=NULL;
//链接在尾指针后
r->next=s;
//尾指针后移
r=s;
scanf("%d",&i);
}
return p;
}




int main()
{
List *L;
L=(List*)malloc(sizeof(List));
//L=Insert_Head(L);
L=Insert_Tail(L);
ShowList(L);
free(L);
return 0;
}





<think>好的,用户之前问过如何创带头结点的单链表,现在他们想知道如何实现头插法尾插法。我需要先回顾之前的回答,确保内容连贯。 首先,用户可能正在学习数据结构,特别是单链表的基本操作。他们可能已经掌握了链的创,现在想进一步学习入元素的方。我需要详细解释头插法尾插法的区别,以及具体实现步骤。 头插法是在链的头部入新节点,也就是头结点之后的位置。而尾插法则是在链的末尾添加新节点。这两种方的关键区别在于找到入的位置,头插法不需要遍历,直接入即可,效率高;尾插法则需要找到最后一个节点,因此需要遍历链,时间复杂度更高。 接下来,我需要考虑用户可能的疑惑点。比如,头插法会导致元素逆序,而尾插法保持顺序一致。用户可能在实际应用中选择不同的方,比如逆序创头插法,正序则用尾插法。我需要用示例代码来展示这两种方实现解释每一步的作用。 另外,用户可能对指针操作不太熟悉,容易出错。比如,在头插法中,新节点的next指针需要指向原来的第一个节点,而头结点的next指向新节点。如果顺序搞反了,会导致链断裂。同样,尾插法中需要维护一个尾指针,否则每次入都要遍历整个链,影响效率。 我还需要提醒用户注意内存分配错误检查,比如malloc是否成功,避免野指针。同时,在示例代码中加入注释,帮助用户理解每个步骤的目的。最后,比较两种方的优缺点,帮助用户根据实际情况选择合适的方。 总结一下,回答的结构应该包括:定义结构体,分别讲解头插法尾插法的步骤、代码示例、注意事项以及比较两者的区别。确保语言简洁明了,代码正确,符合用户之前接受的格式要求,比如使用$$...$$包裹代码块,行内公式用$...$等。</think>创带头结点单链表头插法尾插法实现步骤如下: --- ### **1. 公共结构定义** 首先定义链结点结构体: ```c typedef struct Node { int data; // 数据域(以整型为例) struct Node *next; // 指针域 } Node, *LinkList; ``` --- ### **2. 头插法** **原理**:新结点入到头结点**之后**,时间复杂度$O(1)$ **效果**:入顺序与链实际存储顺序**相反** $$c void HeadInsert(LinkList L, int e) { // L是头结点指针,e为入元素 Node *s = (Node*)malloc(sizeof(Node)); // 创新结点 if (!s) return; // 内存分配失败检查 s->data = e; // 赋值 s->next = L->next; // 新结点指向原第一个结点 L->next = s; // 头结点指向新结点 } $$ **示例**: 依次入$1 \rightarrow 2 \rightarrow 3$,实际链顺序为$3 \rightarrow 2 \rightarrow 1$ --- ### **3. 尾插法** **原理**:新结点入到链**末尾**,时间复杂度$O(n)$ **效果**:入顺序与链实际存储顺序**相同** $$c void TailInsert(LinkList L, int e) { Node *s = (Node*)malloc(sizeof(Node)); if (!s) return; s->data = e; s->next = NULL; // 新结点作为尾结点 // 找到当前尾结点 Node *tail = L; while (tail->next != NULL) { // 遍历至最后一个结点 tail = tail->next; } tail->next = s; // 原尾结点指向新结点 } $$ **示例**: 依次入$1 \rightarrow 2 \rightarrow 3$,实际链顺序为$1 \rightarrow 2 \rightarrow 3$ --- ### **4. 对比分析** | 特性 | 头插法 | 尾插法 | |------------|-------------------------|-------------------------| | 时间复杂度 | $O(1)$ | $O(n)$ | | 顺序关系 | 入顺序与链顺序相反 | 入顺序与链顺序相同 | | 适用场景 | 逆序构 | 正序构 | --- ### **5. 完整测试代码** $$c int main() { LinkList L = CreateList(); // 创头结点 // 头插法 1->2->3 HeadInsert(L, 1); HeadInsert(L, 2); HeadInsert(L, 3); // 实际链顺序: 3->2->1 // 尾插法 1->2->3 TailInsert(L, 1); TailInsert(L, 2); TailInsert(L, 3); // 实际链顺序: 1->2->3 return 0; } $$ --- ### **关键注意事项** 1. **头插法**需注意指针修改顺序:先连新结点与原链,再断开头结点 2. **尾插法**需要维护尾指针,否则每次入均需遍历链(优化方:可额外定义`tail`指针记录尾结点) 3. 入前必须检查`malloc`返回值,避免操作野指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值