2.3.1单链表的定义

2.3.1单链表的定义

1778656263528

1778656327655

1778656344082

struct LNode{//定义单链表节点类型
    ElemType data;//每个节点存放一个数据元素
    struct LNode *next;// 指针指向下一个节点
};

struct LNode *p=(struct LNode *)malloc(sizeof(struct LNode));

1778656811356

typedef struct LNode{//定义单链表结点类型
    ElemType data;//每个节点存放一个数据元素
    struct LNode *next;// 指针指向下一个节点
}LNode,*LinkList;


struct LNode{
	ElemType data;
    struct LNode *next;
};

typedef struct LNode LNode;
typedef struct LNode *LinkList;

1778657110223

typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;

LNode *GetElem(LinkList L,int i){
    int j=1;
    LNode *p=L->next;
    if(i==0)
        return L;
    if(i<1)
        return NULL;
    while(p!=NULL && j<i){
        p=p->next;
        j++;
    }
    return p;
}
#头插法建立单链表的算法
LinkList List_HradInsert (LinkList &L){
	LNode *s;int x;
    L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    scanf("%d",&x);
    while(x!=9999){
        s=(LNode*)malloc(sizeof(LNode));
        s->data=x;
        s->next=L->next;
        L->next=s;
        scanf("%d",&x);
    }
    return L;
}
#不带头结点的单链表
typedef struct LNode{//定义单链表结点类型
    ElemType data;//每个节点存放一个数据元素
    struct LNode *next;// 指针指向下一个节点
}LNode,*LinkList;

//初始化一个空的链表
bool InitList(LinkList & L){
    L=NULL;//空表,暂时还没有任何结点
    return true;
}

void test(){
	LinkList L;//生成一个指向单链表的指针
    //初始化一个空表
    InitList(L);
    //...后续代码...
}

1778659892390

#带头结点的单链表

typedef struct LNode{//定义单链表结点类型
    ElemType data;//每个节点存放一个数据元素
    struct LNode *next;// 指针指向下一个节点
}LNode,*LinkList;

//初始化一个单链表(带头结点)
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));//分配一个头节点
    if(L==NULL)//内存不足,分配失败
        return false;
    L->next = NULL;//头节点之后暂时还没有节点
    return true;
    
}

void test(){
    LinkList L;//声明一个指向单链表的指针
    //初始化一个空表
    InitList(L);
    //...后续代码...
}

1778660423721

1778660467347

1778660479355

2.3.2_1单链表的插入和删除

按位序插入(带头节点)

ListInsert(&L,i,e):插入操作

1778661634583

//在第i个位置插入元素e(带头结点)
bool ListInsert(LinkList &L,int i,ElemType e){
    if(i<1)
        return false;
    LNode *p;//指针p指向当前扫描到的结点
    int j=0;//当前p指向的是第几个结点
    p = L;//L指向头结点,头结点是第0个结点(不存数据)
    while (p!=NULL && j<i-1){//循环找到第i-1个结点
        p=p->next;
        j++;
    }
    if(p==NULL)//i值不合法
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = e;
    s->next=p->next;
    p->next=s;//讲结点s连到p之后
    return true;//插入成功
}
//线连接后断掉

时间复杂度O(n)

# 按位插入不带头节点
bool ListInsert(LinkList &L,int i,ElemType e){
    if(i<1)
        return false;
    if(i==1){//插入第1个结点的操作与其他结点操作不同
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data = e;
        s->next = L;
        L=s;//头指针指向新的结点
        return true;
    }
    LNode *p;//指针p指向当前扫描到的结点
    int j=1;//当前p指向的是第几个结点
    p=L;//p指向第一个结点(注意不是头结点)
    while(p!=NULL&&j<i-1){//循环找到第i-1个结点
        p=p->next;
        j++;
	}
    if(p==NULL)//i值不合法
        return false;
    LNode *s = (LNode*)malloc(sizeof(LNode));
    s->data = e;
    s->next=p->next;
    p->next =s;
    return true;//插入成功
}

豆包完整可编译

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>  // 解决C语言bool类型未知的问题

typedef int ElemType;
typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;

// 按位插入:不带头结点,C语言二级指针修改头指针
bool ListInsert(LinkList *L,int i,ElemType e){
    // 位序非法
    if(i<1)
        return false;

    // 特殊处理:插入第1个位置(需修改头指针)
    if(i==1){
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data = e;
        s->next = *L;   // 解引用二级指针,获取原第一个结点
        *L = s;         // 解引用二级指针,更新头指针
        return true;
    }

    // i>1 的情况:找第 i-1 个结点
    LNode *p;
    int j=1;
    p = *L;  // 解引用二级指针,从第1个数据结点开始遍历

    // 向后走到第 i-1 个结点
    while(p!=NULL && j<i-1){
        p = p->next;
        j++;
    }

    // i过大,无第i-1结点,插入失败
    if(p==NULL)
        return false;

    // 把s插在p后面
    LNode *s = (LNode*)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;

    return true;
}

// 测试函数(可选,验证插入功能)
void PrintList(LinkList L){
    LNode *p = L;
    while(p != NULL){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

int main(){
    LinkList L = NULL;  // 初始化空链表(不带头结点)
    // 测试插入
    ListInsert(&L, 1, 10);  // 插第1位
    ListInsert(&L, 2, 20);  // 插第2位
    ListInsert(&L, 1, 5);   // 插第1位
    PrintList(L);  // 输出:5 10 20
    return 0;
}

#指定结点的后插操作

//后插操作:在p结点之后插入元素e
bool InsertNextNode(LNode *p,ElemType e){
    if(p==NULL)
        return false;	
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if(s==NULL)//内存分配失败
        return false;
    s->data = e;//用结点s保存数据元素e
    s->next=p->next;
    p->next=s;//将结点s连到p之后
    return true;
}

指定结点的前插操作

1778665334939

//前插操作:在p结点之前插入元素e
bool InsertPriorNode (LNode *p,ElemTpye e){
    if(p==NULL)
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if(s==NULL)
        return false;
    s->next = p->next;
    p->next =s;//新结点s连接到p之后
    s->data=p->data;//将p中元素复制到s中
    p->data=e;//p中元素覆盖为e
    return true;
}
//找不到前驱 直接在后面插入一个结点然后给两个值对换!!!

按位删除(带头节点)

bool ListDelect(LinkList &L,int i,ElemType &e){
    if(i<1)
        return false;
    LNode *p;//指针p指向当前扫描到的结点
    int j=0;//当前p指向的是第几个结点
    p=L;//L指向头结点,头结点是第0个结点(不存数据)
    while(p!=NULL && j<i-1){//循环找到第i-1个结点
        p=p->next;
        j++;
    }
    if (p==NULL)//i值不合法
        return false;
    if(p->next ==NULL)//第i-1个结点之后已无其他结点
        return false;
    LNode *q=p->next;//令q指向被删除结点
    e = q->data;//用e返回元素的值
    p->next = q->next;//将*q结点从链条中断开
    free(q);//释放结点的存储空间
    return true;//删除成功
}

O(n)

//删除指定结点p
bool DeleteNode(LNode *p){
    if(p==NULL)
        return false;
    LNode *q=p->next;//令q指向*p的后继结点
    p->data = p->next->data;//和后继结点交换数据域
    p->next = q->next;//将*q结点从链条中断开
    free(q);//释放后继结点的存储空间
    return true;
}

如果p是最后一个结点

// 删除指定结点 p(兼容尾结点)
bool DeleteNode(LNode *p, LinkList L){  // 必须传入头指针 L
    if(p == NULL)
        return false;

    // 情况1:p 不是最后一个结点 → 用O(1)妙法
    if(p->next != NULL){
        LNode *q = p->next;
        p->data = q->data;
        p->next = q->next;
        free(q);
        return true;
    }

    // 情况2:p 是最后一个结点 → 必须从头找前驱
    else{
        LNode *pre = L;
        // 遍历找到 p 的前驱结点
        while(pre->next != p){
            pre = pre->next;
        }
        pre->next = NULL; // 断开尾结点
        free(p);
        return true;
    }
}

1778667141640

posted @ 2026-05-13 18:23  轻狂书生han  阅读(8)  评论(0)    收藏  举报