C语言及程序设计进阶例程-18 链表中结点的插入和删除

简介: 贺老师教学链接  C语言及程序设计进阶 本课讲解回顾:动态分配和撤销内存#include <stdio.h>#include <malloc.h>struct Student{ int num; float score; struct Student *next;};int main( ){ struct Studen

贺老师教学链接  C语言及程序设计进阶 本课讲解


回顾:动态分配和撤销内存

#include <stdio.h>
#include <malloc.h>
struct Student
{
    int num;
    float score;
    struct Student *next;
};


int main( )
{
    struct Student *p;
    p=malloc(sizeof(struct Student));
    p->num=31001;
    p->score=89.5;
    printf("%d  %.1f\n", p->num, p->score);
    free(p);
    return 0;
}


遍历链表
void traverse(Node *h)
{
    Node *p;
    p = h;  /*p指向头结点*/
    while(p!=NULL)  
    {
        printf("%-5d", p->data);  /*“访问”结点,此处用最简单的操作:读取输出*/
        p = p->next; /*p指向下一个结点,继续处理*/
    }
    printf("\n");
    return;
}


创建一个链表
#include <stdio.h>
#include <malloc.h>
typedef struct NODE
{
    int data;
    struct NODE *next;
} Node;
Node *createLinkList(int n);
void traverse(Node *h);


int main( )
{
    Node *head;
    head = createLinkList(5);
    traverse(head);
    return 0;
}


Node *createLinkList(int n)
{
    Node *h=NULL, *p, *last;  /*h指向头结点,p指向新增结点,last指向尾结点*/
    int d;   /*用于输入要插入的元素的值*/
    int i;
    for(i=0; i<n; i++)
    {
        scanf("%d", &d);
        p = (Node *)malloc(sizeof(Node));  /*p指向新增的结点*/
        p->data = d;    /*为数据域赋值*/
        p->next = NULL;   /*指针域为空*/
        if (h==NULL) /*如果h==NULL为真,说明p为第一个结点,由h指向该结点*/
            h = p;
        else  /*否则,原最后一个结点指向新增的结点,新结点加在链表尾*/
            last->next = p;
        last= p;   /*last保持指向最后一个结点的角色*/
    }
    return h;
};


void traverse(Node *h)
{
    Node *p;
    p = h;  /*p指向头结点*/
    while(p!=NULL)
    {
        printf("%-5d", p->data);  /*“访问”结点,此处用最简单的操作:读取输出*/
        p = p->next; /*p指向下一个结点,继续处理*/
    }
    printf("\n");
    return;
}


插入结点应用——建立有序链表
#include <stdio.h>
#include <malloc.h>
typedef struct NODE
{
    int data;
    struct NODE *next;
} Node;
Node *insertNode(Node *h, int b);
void traverse(Node *h);


int main( )
{
    int b[]= {67, 25, 78, 99, 87},i;
    Node *head=NULL;
    for(i=0; i<5; i++)
        head=insertNode(head, b[i]);
    traverse(head);
    return 0;
}
Node *insertNode(Node *h, int b)
{
    Node *q1=h,*q2,*p;
    p=(Node*)malloc(sizeof(Node));  /*生成新结点*/
    p->data=b;
    if(h==NULL)   /*当前链表为空,p作为首结点*/
    {
        h=p;     /*头结点就是p,将p赋值给h*/
        p->next=NULL;  /*p的指针域赋值为空,表示尚无下一个结点*/
    }
    else if(p->data<h->data) /*要插入的元素值小于首结点元素,插入结点作为首结点*/
    {
        h=p;  /*将头结点h赋值为p*/
        p->next=q1; /*p的下一个结点是原先的首结点(见q1的初始化,其值为h)*/
    }
    else  /*在中间找到插入p的位置,将其插入*/
    {
        /*先找到合适的位置,q1的初值是h,即从头结点开始考察*/
        while((q1!=NULL&&p->data>=q1->data))
        {
            q2=q1;         /*q2记录q1的值*/
            q1=q1->next;   /*q1继续向后试探,直到a1*/
        }
        /*将新结点p插在q2后*/
        p->next=q2->next;  /*p的下一个结点为当前q2的下一结点,即p1*/
        q2->next=p;    /*q2的下一个结点y变为p,不再是q1*/
    }
    return h;
}


void traverse(Node *h)
{
    Node *p;
    p = h;  /*p指向头结点*/
    while(p!=NULL)
    {
        printf("%-5d", p->data);  /*“访问”结点,此处用最简单的操作:读取输出*/
        p = p->next; /*p指向下一个结点,继续处理*/
    }
    printf("\n");
    return;
}


删结点应用——在有序表中删除
#include <stdio.h>
#include <malloc.h>
typedef struct NODE
{
    int data;
    struct NODE *next;
} Node;
Node *insertNode(Node *h, int b);
Node *deleteNode(Node *h, int b);
void traverse(Node *h);


int main( )
{
    int b[]= {67, 25, 78, 99, 87},i;
    Node *head=NULL;
    for(i=0; i<5; i++)
        head=insertNode(head, b[i]);
    traverse(head);
    head=deleteNode(head, 43);
    traverse(head);
    head=deleteNode(head, 78);
    traverse(head);
    return 0;
}
Node *insertNode(Node *h, int b)
{
    Node *q1=h,*q2,*p;
    p=(Node*)malloc(sizeof(Node));  /*生成新结点*/
    p->data=b;
    if(h==NULL)   /*当前链表为空,p作为首结点*/
    {
        h=p;     /*头结点就是p,将p赋值给h*/
        p->next=NULL;  /*p的指针域赋值为空,表示尚无下一个结点*/
    }
    else if(p->data<h->data) /*要插入的元素值小于首结点元素,插入结点作为首结点*/
    {
        h=p;  /*将头结点h赋值为p*/
        p->next=q1; /*p的下一个结点是原先的首结点(见q1的初始化,其值为h)*/
    }
    else  /*在中间找到插入p的位置,将其插入*/
    {
        /*先找到合适的位置,q1的初值是h,即从头结点开始考察*/
        while((q1!=NULL&&p->data>=q1->data))
        {
            q2=q1;         /*q2记录q1的值*/
            q1=q1->next;   /*q1继续向后试探,直到a1*/
        }
        /*将新结点p插在q2后*/
        p->next=q2->next;  /*p的下一个结点为当前q2的下一结点,即p1*/
        q2->next=p;    /*q2的下一个结点y变为p,不再是q1*/
    }
    return h;
}


Node *deleteNode(Node *h, int b)
{
    Node *p, *q;
    p=h;   /*p首先指向头结点*/
    if(h==NULL)  /*链表为空时不能删除*/
        printf("List is null, delete fail.\n");
    else
    {
        /*首先找到要删除的结点*/
        while(b!=p->data&&p->next!=NULL)
        {
            q=p;    /*q记录p的值*/
            p=p->next;   /*p接着指向下一个结点,q一直保持是p的上一个结点*/
        }
        if(b==p->data)   /*要删除的结点p在链表中存在*/
        {
            if(p==h) /*要删除的结点就是头结点时,令h指向p的下一个结点即可*/
                h = p->next;
            else   /*否则,删除q的下一个结点p*/
                q->next = p->next;
            free(p);  /*释放p结点*/
        }
        else
            printf("%d not found, delete fail.\n", b);
    }
    return h;
}


void traverse(Node *h)
{
    Node *p;
    p = h;  /*p指向头结点*/
    while(p!=NULL)
    {
        printf("%-5d", p->data);  /*“访问”结点,此处用最简单的操作:读取输出*/
        p = p->next; /*p指向下一个结点,继续处理*/
    }
    printf("\n");
    return;
}


目录
相关文章
|
21天前
|
存储 算法 C语言
【C语言】深入浅出:C语言链表的全面解析
链表是一种重要的基础数据结构,适用于频繁的插入和删除操作。通过本篇详细讲解了单链表、双向链表和循环链表的概念和实现,以及各类常用操作的示例代码。掌握链表的使用对于理解更复杂的数据结构和算法具有重要意义。
179 6
|
25天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
46 5
|
1月前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
87 4
|
2月前
|
存储 缓存 C语言
C语言:链表和数组有什么区别
C语言中,链表和数组是两种常用的数据结构。数组是一种线性结构,元素在内存中连续存储,通过下标访问,适合随机访问且大小固定的情况。链表由一系列不连续的节点组成,每个节点存储数据和指向下一个节点的指针,适用于频繁插入和删除操作的场景,链表的大小可以动态变化。
|
2月前
|
C语言
无头链表再封装方式实现 (C语言描述)
如何在C语言中实现无头链表的再封装,包括创建节点和链表、插入和删除操作、查找和打印链表以及销毁链表的函数。
29 0
|
2月前
|
C语言
C语言链式结构之有头单链表再封装写法
本文介绍了如何使用C语言对有头单链表进行封装,包括节点的创建、链表的初始化、数据的插入和删除,以及链表的打印等功能。
21 1
|
2月前
|
C语言
C语言结构体链式结构之有头单链表
文章提供了一个C语言实现的有头单链表的完整代码,包括创建链表、插入、删除和打印等基本操作。
36 1
|
1月前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
61 0
|
2月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
36 0
|
3月前
|
C语言
C语言里的循环链表
C语言里的循环链表