C语言链表详解

简介: 文章目录C语言链表详解链表基础链表的优点基本概念创建链表定义一个结构体创建一个链表插入节点删除节点修改节点输出节点完整代码线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列等,线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构(存储结构)上并不一定是连续的,线性表在物理上存储时,通常以顺序表和链式结构的形式存储。


线性表的顺序存储—>顺序表

是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。


线性表的链式存储

线性表中的数据结点在内存中的位置是任意的,即逻辑上相邻的数据元素在物理位置(内存存储的位置)上不一定相邻。


链式存储结构的优点:


空间利用率高需要一个空间就分配一个空间

数据元素的逻辑次序靠节点的指针来指示,插入和删除时不需要移动数据结点,任意位置插入删除时间复杂度为O(1)

链式存储结构的缺点:


存储密度小,每个结点的指针域需要额外占用存储空间。当每个结点的数据域所占字节不多时,指针域所占空间的比重显得很大,存储密度大空间利用率越大。

顺序表因为只有数据域,没有指针域所以它的存储密度为最大1

不过这个问题,一个结点也就多几个指针,最多8个字节,所以若是在现代计算机这点空间已经不算什么,不过如果是像单片机这种嵌入式设备内存较小,所以还是会有一点点影响的


链式存储结构是非随机存取结构,对任一结点的操作都要从头指针依次查找到该节点,算法复杂度较高。

顺序表的优点:


存储密度为1最高,因为没有指针域空间利用率高

随机存取,按位置访问元素的时间复杂度为O(1),直接根据数组下标访问元素

顺序表的缺点:


动态顺序表增容会付出一定性能消耗,其次可能还是会存在一定的空间浪费(不可能扩容的刚刚好)

在头部或者中部左右的插入删除,需要移动元素,时间复杂度为O(N),效率低。

顺序表的缺点就是链表的优点,而链表的缺点就是顺序表的优点,所以说不能说链表一定就比顺序表高级,我们要视情况而定。

二.单链表的介绍

线性表的链式存储

线性表中的数据结点在内存中的位置是任意的,即逻辑上是线性的数据元素在物理位置(内存存储的位置)上不一定相邻。

结点为什么在内存中是随机存储的呢

因为我们产生一个结点要给他分配内存是动态分配出来的(malloc),而分配的结点的内存的地址是随机的,所以结点的地址是随机的,也就是说结点在内存中的存储是随机的。


单链表的一个结点


链表基础

链表的优点

n个节点离散分配

每一个节点之间通过指针相连

每一个节点有一个前驱节点和一个后继节点

首节点没有前驱节点,尾节点没有后继节点


基本概念

首节点:存放第一个有效数据的节点

头节点:在单链表的第一个结点之前附设一个结点,它没有直接前驱,称之为头结点,头结点的数据域可以不存储任何信息,指针域指向第一个节点(首节点)的地址。头结点的作用是使所有链表(包括空表)的头指针非空

头指针:指向头节点的指针

尾节点:存放最后一个有效数据的节点

尾指针:指向尾节点的指针

1b834e99c62a49d1b01ddab9f372e381.png

创建链表

定义一个结构体


typedef struct linklist
{
    int score;//定义数据域
    struct student *next;//定义指针域
}linklist;

创建一个链表


//初始化一个链表 n为链表节点个数
Linklist *linklistcreate(int n)
{
    Linklist *head,*node,*end;//定义头节点,普通节点,尾部节点;
    head = (Linklist*)malloc(sizeof(Linklist));//分配地址
    end = head;//若是空链表,则头尾节点一样
    for(int i =0;i<n;i++)
    {
        node = (Linklist*) malloc(sizeof(Linklist));
        scanf("%d",&node->score);
        end->next = node;
        end=node;
    }
    end->next=NULL;//结束创建
    return head;
}

插入节点

5ccba6a2d4234231828c19c0be68bd36.png


//插入节点
//插入节点就是用插入前节点的指针域链接上插入节点的数据域,再把插入节点的指针域链接上插入后节点的数据域。
//e->next = head->next;  head->next = e
void insert(Linklist *list,int n)
{
    Linklist *t=list,*in;
    int i =0;
    while(i<n&&t!=NULL)
    {
        t = t->next;
        i++;
    }
    if(t!=NULL)
    {
        in = (Linklist*) malloc(sizeof(Linklist));
        puts("请输入要插入的值:");
        scanf("%d",&in->score);
        in->next=t->next;//填充in节点的指针域,也就是说把in的指针域指向t的下一个节点
        t->next=in;//填充t节点的指针域,把t的指针域重新指向in
    }
    else
    {
        puts("节点不存在");
    }
}


删除节点

3c25395a35c24a928c1356619a5ba627.png

//删除链表节点
//删除链表的元素也就是把前节点的指针域越过要删除的节点指向下下个节点。
// 即:p->next = q->next;然后放出q节点的空间,即free(q);
void delete(Linklist *list,int n)
{
    Linklist  *t = list,*in;
    int i =0;
    while(i<n && t != NULL)
    {
        in = t;
        t = t->next;
        i++;
    }
    if(t != NULL)
    {
        in->next= t->next;
        free(t);
    }
    else
    {
        puts("节点不存在");
    }
}


修改节点

//修改链表节点值
void change(Linklist *list,int n)
{
    Linklist *t = list;
    int i = 0;
    while (i<n&&t!=NULL)
    {
        t = t->next;
        i++;
    }
    if(t!=NULL)
    {
        puts("输入要修改的值:");
        scanf("%d",&t->score);
    }
    else
    {
        puts("节点不存在");
    }
}


输出节点


void output(Linklist *head,int n)
{
    Linklist *h = head;
    int i =0;
    while (h != NULL)
    {
        h =h->next;
        printf("%d",h->score);
    }
}

完整代码


#include<stdio.h>
#include <malloc.h>
#include <stdbool.h>
//定义结构体
typedef struct linklist{
    int score;//定义数据域
    struct student *next;//定义指针域
}Linklist;
Linklist *linklistcreate(int n);
void insert( Linklist *head,int n);
void delete(Linklist *head,int n);
void change(Linklist *head,int n);
void output(Linklist *head,int n);
int main(){
    int n,in,x,y;
    char c;
    struct Linklist *head  =NULL;
    printf("请输入要创建的节点个数:\n");
    scanf("%d",&n);
    head = linklistcreate(n);
    printf(head);
    while (true){
        printf("请选择要执行的操作:\n");
        printf("1.插入节点\n2.删除节点\n3.修改节点\n4.退出\n");
        scanf("%c",&c);
        if(c =='1'){
            printf("你想要在哪插入节点:\n");
            scanf("%c",&in);
            insert(head,in);
            printf(head);
            output(head,n);
        }else if(c == '2'){
            printf("你想要删除哪个节点的数据:\n");
            scanf("%d",&x);
            delete(head,x);
            printf(head);
        }else if(c =='3'){
            printf("你想要修改哪个节点的数据:\n");
            scanf("%d",&y);
            change(head,y);
            printf(head);
        }else if(c =='4'){
            exit(0);
        }
    }
}
//初始化一个链表 n为链表节点个数
Linklist *linklistcreate(int n){
    Linklist *head,*node,*end;//定义头节点,普通节点,尾部节点;
    head = (Linklist*)malloc(sizeof(Linklist));//分配地址
    end = head;//若是空链表,则头尾节点一样
    for(int i =0;i<n;i++){
        node = (Linklist*) malloc(sizeof(Linklist));
        scanf("%d",&node->score);
        end->next = node;
        end=node;
    }
    end->next=NULL;//结束创建
    return head;
}
//插入节点
//插入节点就是用插入前节点的指针域链接上插入节点的数据域,再把插入节点的指针域链接上插入后节点的数据域。
//e->next = head->next;  head->next = e
void insert(Linklist *list,int n){
    Linklist *t=list,*in;
    int i =0;
    while(i<n&&t!=NULL){
        t = t->next;
        i++;
    }
    if(t!=NULL){
        in = (Linklist*) malloc(sizeof(Linklist));
        puts("请输入要插入的值:");
        scanf("%d",&in->score);
        in->next=t->next;//填充in节点的指针域,也就是说把in的指针域指向t的下一个节点
        t->next=in;//填充t节点的指针域,把t的指针域重新指向in
    }
    else{
        puts("节点不存在");
    }
}
//删除链表节点
//删除链表的元素也就是把前节点的指针域越过要删除的节点指向下下个节点。
// 即:p->next = q->next;然后放出q节点的空间,即free(q);
void delete(Linklist *list,int n){
    Linklist  *t = list,*in;
    int i =0;
    while(i<n && t != NULL){
        in = t;
        t = t->next;
        i++;
    }
    if(t != NULL){
        in->next= t->next;
        free(t);
    }
    else{
        puts("节点不存在");
    }
}
//修改链表节点值
void change(Linklist *list,int n)
{
    Linklist *t = list;
    int i = 0;
    while (i<n&&t!=NULL)
    {
        t = t->next;
        i++;
    }
    if(t!=NULL)
    {
        puts("输入要修改的值:");
        scanf("%d",&t->score);
    }
    else
    {
        puts("节点不存在");
}
void output(Linklist *head,int n)
{
    Linklist *h = head;
    int i =0;
    while (h != NULL)
    {
        h =h->next;
        printf("%d",h->score);
    }
}

链表相关练习

#include "ChainList.h"
/*初始化链表*/
bool Init(ChainListType *head)  
{  
    head = (ChainListType *)malloc(sizeof(ChainListType));
  if(head == NULL)
  {
    printf("初始化失败!\n");
    return false;
  }
  head->next=NULL;
  return true;
}  
/*获取链表结点数量*/
int Length(ChainListType *head)
{
    ChainListType *p;
    int i=0;
    p=head;
    while(p)     //遍历整个链表 
    {
        i++;    //累加结点数量 
        p=p->next;  //处理下一结点 
    }
    return i;   //返回结点数量 
}
/*添加结点到链表结尾*/
ChainListType *AddEnd(ChainListType *head,DATA data)  
{
    ChainListType *node,*p;
    if(!(node=(ChainListType *)malloc(sizeof(ChainListType))))
    {
        printf("为保存结点数据申请内存失败!\n"); 
        return NULL;  //分配内存失败 
    }
    node->data=data;  //保存数据 
    node->next=NULL;  //设置结点指针为空,即为表尾 
  //是头指针 
  if(head==NULL)    
    {
        head=node;
        return head;
    }
  //不是头指针 
    p=head;
    while(p->next!=NULL) //查找链表的末尾 
        p=p->next ;
    p->next=node;
    return head;
}
/*添加结点到链表首部*/
ChainListType *AddFirst(ChainListType *head,DATA data) 
{
    ChainListType *node;
    if(!(node=(ChainListType *)malloc(sizeof(ChainListType))))
    {
        printf("为保存结点数据申请内存失败!\n"); 
        return NULL;  //分配内存失败 
    }
    node->data=data; //保存数据 
    node->next=head;  //指向头指针所指结点 
    head=node;        //头指针指向新增结点
    return head; 
}
/*插入结点到链表指定位置*/
ChainListType *Insert(ChainListType *head,char *findkey,DATA data)  
{
    ChainListType *node,*node1;    
    if(!(node=(ChainListType *)malloc(sizeof(ChainListType)))) //分配保存结点的内容 
    {
        printf("为保存结点数据申请内存失败!\n"); 
        return 0;  //分配内存失败 
    }
    node->data=data;  //保存结点中的数据 
    node1=Find(head,findkey);
    if(node1)  //若找到要插入的结点 
    {
        node->next=node1->next;  //新插入结点指向关键结点的下一结点 
        node1->next=node;    //设置关键结点指向新插入结点 
    }
  else
  {
        free(node);//释放内存
        printf("未找到插入位置!\n"); 
    }
    return head;//返回头指针
}
/*按关键字在链表中查找内容*/ 
ChainListType *Find(ChainListType *head,char *key) 
{
    ChainListType *p;
    p=head;       //保存链表头指针 
    while(p)      //若结点有效,则进行查找 
    {
        if(strcmp(p->data.key,key)==0) //若结点关键字与传入关键字相同 
            return p;  //返回该结点指针 
        p=p->next; //处理下一结点 
    }
    return NULL; //返回空指针 
}
/*删除指定关键字的结点*/
bool Delete(ChainListType *head,char *key)
{
    ChainListType *node,*p; //node保存删除结点的前一结点 
    node=p=head;    
    while(p)
    {
        if(strcmp(p->data.key,key)==0) //找到关键字,执行删除操作 
        {
            node->next=p->next;      //使前一结点指向当前结点的下一结点
            free(p);           //释放内存 
            return true; 
        }
    else
    {
            node=p;   //指向当前结点 
            p=p->next;  //指向下一结点 
        }
     }
     return false;    //未删除 
}
/*遍历链表*/ 
void ShowAll(ChainListType *head) 
{
    ChainListType *h;
    DATA data;
    h=head;
    printf("链表所有数据如下:\n"); 
    while(h)      //循环处理链表每个结点 
    {
        data=h->data; //获取结点数据 
        printf("(%s,%s,%d)\n",data.key,data.name,data.age); 
        h=h->next;    //处理下一结点 
    }
    return;
}
/*销毁链表*/
bool Destory(ChainListType *head)
{
  ChainListType *p=NULL;
  if(head == NULL)
    return false;
  while(head)
  {
    p=head->next;
    free(head);
    head=p;
  }
  return true;
}
#include <stdio.h>
#include <stdlib.h>
struct grade {
    int score;
    struct grade *next;
};
typedef struct grade NODE;  //typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。
//使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,
//另一个是简化一些比较复杂的类型声明。
struct grade *create();   //创建链表
void insert(NODE *head,NODE *pnew,int i);   //插入链表
void pdelete(NODE *head,int i);   //删除列表
void display(NODE *head);   //输出链表
void Pfree(NODE *head);    //销毁链表
int main(int argc, char *argv[]) {
    struct grade *head,*pnew;
    head=create();
    if (head==NULL)
        return 0;
    printf("输出创建的链表:");
    display(head);
    pnew=(NODE *)malloc(sizeof(NODE));
    if (pnew==NULL) {
        printf("创建失败!");
        return 0;
    }
    pnew->score=88;
    insert(head,pnew, 3);   //将新节点插入节点3的后面
    printf("插入后的链表:");
    display(head);
    pdelete(head,3);   //删除节点3
    printf("删除后的链表:");
    display(head);
    Pfree(head);
    return 0;
}
struct grade *create() {
    NODE *head,*tail,*pnew;
    int score;
    head=(NODE *)malloc(sizeof(NODE));  //创建头节点。
    if (head==NULL) { //创建失败返回
        printf("创建失败!");
        return NULL;
    }
    head->next=NULL;  //头节点指针域置NULL
    tail=head;  // 开始时尾指针指向头节点
    printf("输入学生成绩:");
    while (1) { //创建链表
        scanf("%d",&score);
        if (score<0) //成绩为负是退出循环
            break;
        pnew=(NODE *)malloc(sizeof(NODE));  //创建新节点
        if (pnew==NULL) { //创建失败返回
            printf("创建失败!");
            return NULL;
        }
        pnew->score=score;  //新节点数据域存放输入的成绩
        pnew->next=NULL;   //新节点指针域置NULL
        tail->next=pnew;  //新节点插入到表尾
        tail=pnew;   //为指针指向当前的尾节点
    }
    return head;  //返回创建链表的头指针
}
void insert(NODE *head,NODE *pnew,int i) {
    NODE *p; //当前指针
    int j;
    p=head;
    for (j=0; j<i&&p!=NULL; j++) //p指向要插入的第i个节点
        p=p->next;
    if (p==NULL) { //节点i不存在
        printf("与插入的节点不存在!");
        return;
    }
    pnew->next=p->next;   //插入节点的指针域指向第i个节点的后继节点
    p->next=pnew;    //犟第i个节点的指针域指向插入的新节点
}
void pdelete(NODE *head,int i) {
    NODE *p,*q;
    int j;
    if (i==0) //删除的是头指针,返回
        return;
    p=head;
    for (j=1; j<i&&p->next!=NULL; j++)
        p=p->next;  //将p指向要删除的第i个节点的前驱节点
    if (p->next==NULL) { //表明链表中的节点不存在
        printf("不存在!");
        return;
    }
    q=p->next;  //q指向待删除的节点
    p->next=q->next;  //删除节点i,也可写成p->next=p->next->next
    free(q);   //释放节点i的内存单元
}
void display(NODE *head) {
    NODE *p;
    for (p=head->next; p!=NULL; p=p->next)
        printf("%d ",p->score);
    printf("\n");
}
void pfree(NODE *head) {
    NODE *p,*q;
    p=head;
    while (p->next!=NULL) { //每次删除头节点的后继节点
        q=p->next;
        p->next=q->next;
        free(q);
    }
    free(head);   //最后删除头节点
}
void Pfree(NODE *head) {
    NODE *p,*q;
    p=head;
    while (p->next!=NULL) {
        q=p->next;
        p->next=q->next;
        free(q);
    }
    free(p);
}
#include <stdio.h>
#include <malloc.h>
#include <conio.h>
#include <stdlib.h>
//链表单元定义,链表相关变量
struct student {
    int id;
    float score;
    struct student *next;
} *head,*pthis;
//输入数据创建链表
void input() {
    struct student *tmp;
    printf("\n\n请输入学生的信息以学号为0结束:\n");
    do {
        printf("ID\t成绩\n");
        if ((tmp=(struct student *)malloc(sizeof(struct student)))==NULL) {
            printf("\n错误!不能申请所需的内存!\n");
            exit(0);
        }
        scanf("%d\t%f",&tmp->id,&tmp->score);
        tmp->next=NULL;
        if (tmp->id!=0) {
            if (head==NULL) {
                head=tmp;
                pthis=head;
            } else {
                pthis->next=tmp;
                pthis=pthis->next;
            }
        }
    } while (tmp->id!=0);
    free(tmp);
}
//搜索链表找到第一个符合条件的项目输出
void search(int id) {
    printf("\n\n查询结果\n");
    printf("ID\t成绩\n");
    printf("-------------------------------\n");
    if (head==NULL) {
        printf("\n错误!没有数据!\n");
        return;
    }
    pthis=head;
    while (pthis!=NULL) {
        if (pthis->id==id) {
            printf("%d\t%.2f\n",pthis->id,pthis->score);
            return;
        } else {
            pthis=pthis->next;
        }
    }
    printf("\n没有找到!\n");
}
//列表输出链表中的所有项
void list() {
    printf("\n\n数据列表\n");
    printf("ID\t成绩\n");
    printf("-------------------------------\n");
    if (head==NULL) {
        printf("错误,没有数据!\n");
        return;
    }
    pthis=head;
    while (pthis!=NULL) {
        printf("%d\t%.2f\n",pthis->id,pthis->score);
        pthis=pthis->next;
    }
}
//插入数据
void insert() {
    int i,p;
    struct student *tmp;
    if (head==NULL) {
        printf("\n\n数据不存在,无法插入!\n");
        return;
    }
    printf("\n请输入插入点:\n");
    scanf("%d",&p);
    if (p<0) {
        printf("输入不合法!");
        return;
    }
    printf("\n\n请输入学生的信息:\nID\t成绩\n");
    if ((tmp=(struct student *)malloc(sizeof(struct student)))==NULL) {
        printf("\n错误!不能申请所需的内存!\n");
        exit(0);
    }
    scanf("%d\t%f",&tmp->id,&tmp->score);
    tmp->next=NULL;
    if (tmp->id!=0) {
        pthis=head;
        if (p==0) {
            tmp->next=head;
            head=tmp;
        } else {
            for (i=0; i<p-1; i++) {
                if (pthis->next->next==NULL) {
                    printf("\n找不到插入点,您输入的数据太大!\n");
                    return;
                }
                pthis=pthis->next;
            }
            tmp->next=pthis->next;
            pthis->next=tmp;
        }
    } else {
        printf("\n数据无效!\n");
        free(tmp);
    }
}
//追加数据
void append() {
    struct student *tmp;
    printf("\n\n请输入学生的信息:\nID\t成绩\n");
    if ((tmp=(struct student *)malloc(sizeof(struct student)))==NULL) {
        printf("\n错误!不能申请所需的内存!\n");
        exit(0);
    }
    scanf("%d\t%f",&tmp->id,&tmp->score);
    tmp->next=NULL;
    if (tmp->id!=0) {
        if (head==NULL) {
            head=tmp;
        } else {
            pthis=head;
            while (pthis->next!=NULL) {
                pthis=pthis->next;
            }
            pthis->next=tmp;
        }
    } else {
        free(tmp);
        printf("\n数据无效!\n");
    }
}
//删除数据
void del() {
    int p,i;
    struct student *tmp;
    if (head==NULL) {
        printf("\n\n没有数据,无法删除!\n");
        return;
    }
    printf("\n\n请输入要删除的记录号:\n");
    scanf("%d",&p);
    if (p<0) {
        printf("\n输入不合法!\n");
        return;
    }
    if (p==0) {
        pthis=head;
        head=pthis->next;
        free(pthis);
        pthis=head;
    } else {
        pthis=head;
        for (i=0; i<p-1; i++) {
            pthis=pthis->next;
            if (pthis->next==NULL) {
                printf("\n\n指定记录不存在,无法删除!\n");
                return;
            }
        }
        tmp=pthis->next;
        pthis->next=pthis->next->next;
        free(tmp);
    }
}
//程序主函数
void main() {
    char command=0;
    int id=0;
//主循环
    do {
        printf("\n\n\t 菜单\n");
        printf("-------------------------------\n");
        printf("\ta,输入数据\n");
        printf("\tb,查询记录\n");
        printf("\tc,数据列表\n");
        printf("\td,追加记录\n");
        printf("\te,插入记录\n");
        printf("\tf,删除记录\n");
        printf("\tg,退出系统\n");
        printf("-------------------------------\n");
        printf("\t请选择:");
        command=getch();
//命令处理
        switch (command) {
        case 'a':
            if (head==NULL) {
                input();
                break;
            } else {
                printf("\n\n数据已经存在!\n");
                break;
            }
        case 'b':
            printf("\n\n要查询的ID:");
            scanf("%d",&id);
            search(id);
            break;
        case 'c':
            list();
            break;
        case 'd':
            append();
            break;
        case 'e':
            insert();
            break;
        case 'f':
            del();
            break;
        }
    } while (command!='g');
}
#include "ChainList.h"
int main()
{
    ChainListType *node, *head=NULL;
    DATA data;
    char key[15],findkey[15];
  //初始化链表
  Init(head);
  printf(printf("该链表共有%d个结点。\n",Length(head));
  //添加结点(尾部)
    printf("输入链表中的数据,包括关键字、姓名、年龄,关键字输入0,则退出:\n"); 
    do
  {
        fflush(stdin);  //清空输入缓冲区 
        scanf("%s",data.key);
        if(strcmp(data.key,"0")==0) break; //若输入0,则退出
        scanf("%s%d",data.name,&data.age);
        head=AddEnd(head,data);//在链表尾部添加结点数据 
    }while(1);
  //返回结点数量 
    printf("该链表共有%d个结点。\n",Length(head)); 
    ShowAll(head); //显示所有结点
  //插入结点
    printf("\n插入结点,输入插入位置的关键字:") ;
    scanf("%s",&findkey);//输入插入位置关键字 
    printf("输入插入结点的数据(关键字 姓名 年龄):");
    scanf("%s%s%d",data.key,data.name,&data.age);//输入插入结点数据 
    head=Insert(head,findkey,data);//调用插入函数 
  //显示所有结点
    ShowAll(head); 
  //查找结点
    printf("\n在链表中查找,输入查找关键字:");
    fflush(stdin);//清空输入缓冲区 
    scanf("%s",key);//输入查找关键字 
    node=Find(head,key);//调用查找函数,返回结点指针 
    if(node)//若返回结点指针有效 
    {
        data=node->data;//获取结点的数据 
        printf("关键字%s对应的结点数据为(%s,%s,%d)\n" ,key,data.key,data.name,data.age);        
    }
  else//若结点指针无效 
        printf("在链表中未找到关键字为%s的结点!\n",key); 
  //删除结点:
    printf("\n在链表中删除结点,输入要删除的关键字:");
    fflush(stdin);//清空输入缓冲区 
    scanf("%s",key);//输入删除结点关键字 
    Delete(head,key); //调用删除结点函数 
    ShowAll(head); //显示所有结点   
  //销毁链表
  Destory(head);
    getchar();
    return 0;
}




相关文章
|
19天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
45 4
|
1月前
|
存储 缓存 C语言
C语言:链表和数组有什么区别
C语言中,链表和数组是两种常用的数据结构。数组是一种线性结构,元素在内存中连续存储,通过下标访问,适合随机访问且大小固定的情况。链表由一系列不连续的节点组成,每个节点存储数据和指向下一个节点的指针,适用于频繁插入和删除操作的场景,链表的大小可以动态变化。
|
1月前
|
C语言
无头链表再封装方式实现 (C语言描述)
如何在C语言中实现无头链表的再封装,包括创建节点和链表、插入和删除操作、查找和打印链表以及销毁链表的函数。
26 0
|
1月前
|
C语言
C语言链式结构之有头单链表再封装写法
本文介绍了如何使用C语言对有头单链表进行封装,包括节点的创建、链表的初始化、数据的插入和删除,以及链表的打印等功能。
16 1
|
1月前
|
C语言
C语言结构体链式结构之有头单链表
文章提供了一个C语言实现的有头单链表的完整代码,包括创建链表、插入、删除和打印等基本操作。
22 1
|
19天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
38 0
|
1月前
|
测试技术 C语言
单链表之无头链表(C语言版)
本文详细介绍了使用C语言实现无头单链表的方法,包括节点和链表结构的定义、链表的创建与销毁、节点的插入与删除,以及链表的打印等功能。文章通过具体的代码示例,展示了如何在无头链表中进行头插法、尾插法、自定义位置插入和删除,以及如何清空和销毁链表。
32 0
单链表之无头链表(C语言版)
|
5月前
|
存储 缓存 前端开发
【数据结构/C语言】深入理解 双向链表
【数据结构/C语言】深入理解 双向链表
|
1月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
24 0
|
2月前
|
存储 C语言
C语言程序设计核心详解 第九章 结构体与链表概要详解
本文档详细介绍了C语言中的结构体与链表。首先,讲解了结构体的定义、初始化及使用方法,并演示了如何通过不同方式定义结构体变量。接着,介绍了指向结构体的指针及其应用,包括结构体变量和结构体数组的指针操作。随后,概述了链表的概念与定义,解释了链表的基本操作如动态分配、插入和删除。最后,简述了共用体类型及其变量定义与引用方法。通过本文档,读者可以全面了解结构体与链表的基础知识及实际应用技巧。