不带头结点的单链表插入方法(头插法与尾插法)

不带头结点的单链表插入方法(头插法与尾插法)

在这里插入图片描述

在C++中,单链表是一种常见的数据结构,在动态数据管理方面有着广泛的应用。本文将介绍不带头结点的单链表实现,并采用头插法尾插法进行插入操作,最后输出链表中的元素。

1. 链表结构体定义

首先,我们定义一个LNode结构体来表示单链表的结点:

typedef struct LNode{
    int data;        // 数据域
    struct LNode *next;  // 指针域,指向下一个结点
}LNode, *LinKL;

在本示例中,链表不带头结点,即L直接指向首个数据结点。

2. 初始化链表

在使用链表前,我们需要进行初始化:

void init(LinKL &L) {
    L = NULL;  // 让链表指针为空,表示链表为空
}

此函数将链表指针L置空,确保其处于可用状态。

3. 头插法实现

头插法的特点是每次插入新结点时,让其成为新的头结点,即新数据的插入顺序与输入顺序相反。

代码实现:

bool InsertL(LinKL &L, int &e) {
    while (e != 9999) {  // 9999 代表输入结束
        LNode *p = (LNode*)malloc(sizeof(LNode));
        if (!p) return false;  // 内存分配失败

        p->data = e;
        p->next = L;  // 让新结点指向当前的头结点
        L = p;  // 更新头指针

        scanf("%d", &e);  // 读取下一个元素
    }
    return true;
}

代码解析:

  • 申请一个新结点 p,存储当前输入值。
  • p->next 指向当前链表头 L,然后 L 更新为 p,使 p 成为新的头结点。
  • 读取下一个数据,继续插入,直到遇到 9999 结束。

4. 尾插法实现

尾插法的特点是每次插入新结点时,让其成为链表的尾部结点,因此新数据的插入顺序与输入顺序相同。

代码实现:

bool InsertTail(LinKL &L, int &r) {
    LNode *p = NULL;  // 尾指针,初始为空
    while (r != 9999) {
        LNode *s = (LNode*)malloc(sizeof(LNode));
        if (!s) return false;  // 内存分配失败

        s->data = r;
        s->next = NULL;  // 新结点的 next 置空

        if (L == NULL) {
            L = s;  // 如果链表为空,新结点直接作为头结点
        } else {
            p->next = s;  // 否则,当前尾结点指向新结点
        }
        p = s;  // 更新尾指针

        scanf("%d", &r);  // 读取下一个元素
    }
    return true;
}

代码解析:

  • 使用 p 作为尾指针,指向当前链表的最后一个结点。
  • 如果链表为空,则让 L = s,表示 s 是首个结点。
  • 否则,将 p->next 设为 s,然后 p 指向 s,即 s 成为新的尾结点。
  • 依次读取数据,直到遇到 9999 结束。

5. 输出链表

由于OJ判题对空格敏感,必须按照指定格式输出:

void PrintList(LinKL L) {
    while (L) {
        printf("%d", L->data);
        L = L->next;
        if (L) printf(" ");  // 仅在下一个结点存在时打印空格
    }
    printf("\n");
}

代码解析:

  • 遍历链表,每次打印当前结点的数据 L->data
  • 如果 L->next 存在,则打印一个空格,确保格式正确。

6. 主函数实现

int main() {
    LinKL L;
    init(L);  // 初始化头插法链表

    int e;
    scanf("%d", &e);
    InsertL(L, e);  // 头插法插入数据
    PrintList(L);    // 输出头插法结果

    LinKL L2;
    init(L2);  // 初始化尾插法链表

    int r;
    scanf("%d", &r);
    InsertTail(L2, r);  // 尾插法插入数据
    PrintList(L2);      // 输出尾插法结果

    return 0;
}

代码解析:

  1. 初始化两个链表 LL2,分别用于头插法和尾插法。
  2. 读取数据并插入到链表中。
  3. 使用 PrintList() 进行格式化输出。

7. 代码运行示例

输入:

3 4 5 6 7 9999

输出:

7 6 5 4 3  // 头插法的结果(倒序)
3 4 5 6 7  // 尾插法的结果(顺序)

结果分析:

  • 头插法的结果是输入顺序的逆序
  • 尾插法的结果与输入顺序一致

8. 总结

 //输入3 4 5 6 7 9999一串整数,9999代表结束,通过头插法新建链表,并输出,通过尾插法新建链表,并输出。
//
//注意输出要采用如下代码(因为OJ判题对空格敏感,因此需要用下面的打印代码来做)
打印链表中每个结点的值
//void PrintList(LinkList L)
//{
//    L=L->next;
//    while(L!=NULL)
//    {
//        printf("%d",L->data);//打印当前结点数据
//        L=L->next;//指向下一个结点
//        if(L!=NULL)
//        {
//            printf(" ");
//        }
//    }
//    printf("\n");
//}


//使用头插法 实现链表的插入操作 不带头结点 L直接指向数据结点
#include <iostream>
#include<stdio.h>

//定义链表结构体
typedef struct LNode{
    int data;
    struct LNode *next;
}LNode ,*LinKL;
//初始化 不带头结点
 void init(LinKL &L){
     L =NULL;
 }
 //头插入
 bool InsertL(LinKL &L,int &e){
     
    while(e!=9999){  //一直读入数据,直到9999
        LNode * p= (LNode*) malloc(sizeof(LNode));
        if(!p){ //分配失败
            return false;
        }
        p->data = e;
        p->next =L; //指向L原来指的地方
        L = p; //在将L 指向p
        scanf("%d",&e);
    }

     return true;
 }
 //多定义一个尾指针 p
 bool InsertTail(LinKL &L, int &r){
     while(r!=9999){
         LNode *s,*p = NULL; //tail
         s =(LNode*) malloc(sizeof(LNode));
         if(!s) return false;
         //插入数据
         s->data = r;
         s->next = NULL;
         //s 指向L
         if(L==NULL){
             L = s;

         }
         p->next =s;
         p = s;

         scanf("%d",&r);

     }

     return true;
 }

 bool Print1(LinKL L ){
         while (L) {
             printf("%d", L->data);
             L = L->next;
             if (L) printf(" ");  // 仅在下一个节点存在时打印空格
         }
         printf("\n");
     return true;
 }

// void Print(LinKL L){
//     LNode *p =L;
//     while(p){
//         printf("%d->",p->data);
//         p =p->next;
//
//     }
//     printf("NULL");
// }



int main() {i                                                                                                                                                                                                                                                                                                                                      
    LinKL L;
    //初始化
    init(L);
    //插入头
    int e ;
    scanf("%d",&e);
    InsertL(L,e);

    Print1( L);
   // PrintList(L);
//尾插
    LinKL  L2;
    init(L2);

    int r;
    scanf("%d",&r);
    InsertTail(L2,r);
    Print1(L2);

    return 0;
}

本文介绍了不带头结点的单链表插入方法,包括:

  • 头插法(逆序插入)
  • 尾插法(顺序插入)
  • 链表输出(保证OJ格式)

自己实践的完整代码 有错误请指正。
在这里插入图片描述

掌握这两种插入方法,对于理解单链表的基本操作至关重要。希望本文能帮助新手更好地学习C++链表的实现! 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yhame.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值