首页 > 其他分享 >C语言链表

C语言链表

时间:2023-06-01 18:02:34浏览次数:42  
标签:SLIST C语言 next 链表 pCur pHead NULL 节点


#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

/*
struct Teacher 
{
    char name[64];
    int id;
    char *p;
    char **p2;
};
typedef struct Teacher Teacher ;
*/


typedef struct Student 
{
    char name[64];
    int id;

}Student;

typedef struct Teacher 
{
    char name[64];
    int id;
    char *p;
    char **p2;
    Student s1;
    Student *p3;
}Teacher;

//1 结构体中套一个结构体
//2             结构体的指针
//3 结构中套一个 自己类型的结构体元素。。。err
//4 结构体中 套一个 指向自己类型的指针

//数据类型本质:固定大小内存块的别名 

/*
typedef struct AdvTeacher 
{
    char name[64];
    int id;
    struct AdvTeacher AdvTeacher;
}AdvTeacher;  //在自己类型大小 还没有确定的情况下 引用自己类型的元素 是不正确的
//结构体不能嵌套定义 (确定不了数据类型的内存大小,分配不了内存)
*/

typedef struct AdvTeacher2 
{
    char name[64];
    int id;
    struct AdvTeacher2 *p2;
}AdvTeacher;


//函数的嵌套调用  和 结构数据类型嵌套定义 是两个不同的概念
void main11()
{
    Teacher t1;
    //AdvTeacher  advT1; //
    printf("hello...\n");
    system("pause");
    main();
    return ;
}
#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

//类
typedef struct Teacher
{
    int data;
    struct Teacher *next;
}Teacher;

//静态链表
//固定个数  结点的内存生命周期

//动态链表
Teacher *CreatlIST(Teacher **retHead, Teacher **retEnd, Teacher **retmid)
{
    static Teacher t1, t2, t3,t4;
    Teacher *p = NULL;
    t1.data = 1;
    t2.data = 2;
    t3.data = 3;
    t4.data = 4;

    t1.next = &t2;
    t2.next = &t3;
    t3.next = &t4;
    t4.next = 0;


    p = &t1;
    while (p)
    {
        printf("data:%d \n", p->data);
        p = p->next; //指针的下移 
    }
    *retHead = &t1;
    *retEnd = &t4;
    *retmid = &t2;
    return  &t4;
}
void main()
{
    Teacher *head;
    Teacher *end;
    Teacher *end2;
    Teacher *mid;
    end2 = CreatlIST(&head,&end,&mid);
    printf("head:%d\n",head->data);
    printf("end:%d\n", end->data);
    printf("end:%d\n", end2->data);
    printf("mid:%d\n", mid->data);
    printf("hello...\n");
    system("pause");
    return;
}

C语言链表_链表

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

typedef struct Node
{
    int data;
    struct Node *next;
}SLIST;

SLIST *SList_Create(); //创建链表
int SList_Print(SLIST *pHead); //遍历链表
int SList_NodeInsert(SLIST *pHead, int x, int y); //插入值  在x值之前 删除y
int SList_NodeDel(SLIST *pHead, int y);
int SList_Destory(SLIST *pHead);


SLIST *SList_Create()
{

    SLIST *pHead, *pM, *pCur;
    int     data;
    //创建头节点 并初始化
    pHead = (SLIST *)malloc(sizeof(SLIST));
    if (pHead == NULL)
    {
        return NULL;
    }
    pHead->data = 0;
    pHead->next = NULL;

    printf("\nplease enter you data: ");
    scanf("%d", &data);

    pCur = pHead;

    while (data != -1)
    {
        //创建业务节点 并初始化 不断接受输入 malloc新结点
        pM = (SLIST *)malloc(sizeof(SLIST));
        if (pM == NULL)
        {
            return NULL;
        }
        pM->data = data;
        pM->next = NULL;

        //2 新结点 入链表 
        pCur->next = pM;

        //3 新结点变成当前节点
        pCur = pM;  //链表结点的尾部追加 

        printf("\nplease enter you data: ");
        scanf("%d", &data);
    }

    return pHead;
}
int SList_Print(SLIST *pHead)
{
    SLIST *tmp = NULL;
    if (pHead == NULL)
    {
        return -1;
    }
    tmp = pHead->next;

    printf("\nBegin\t");
    while (tmp)
    {
        printf("%d ", tmp->data);
        tmp = tmp->next;
    }
    printf("\tEnd");
    return 0;
}

int SList_NodeInsert(SLIST *pHead, int x, int y)
{
    SLIST *pM, *pCur, *pPre;

    //创建新的业务节点pM
    pM = (SLIST *)malloc(sizeof(SLIST));
    if (pM == NULL)
    {
        return -1;
    }
    pM->next = NULL;
    pM->data = y;

    //遍历链表
    pPre = pHead;
    pCur = pHead->next;

    while (pCur)
    {
        if (pCur->data == x)
        {
            break;
        }
        pPre = pCur;
        pCur = pCur->next;
    }

    //让新结点 连接 后续链表
    pM->next = pPre->next;
    //让前驱节点 连接 新结点
    pPre->next = pM;

    return 0;
}

int SList_NodeDel(SLIST *pHead, int y)
{
    SLIST  *pCur, *pPre;

    //初始化状态

    pPre = pHead;
    pCur = pHead->next;

    while(pCur != NULL)
    {
        if (pCur->data == y)
        {
            break;
        }
        pPre = pCur;
        pCur = pCur->next;
    }

    //删除操作
    if (pCur == NULL)
    {
        printf("没有找到结点值为:%d 的结点\n", y);
        return -1;
    }
    pPre->next = pCur->next;
    if (pCur != NULL)
    {
        free(pCur);
    }
    return 0;
}

int SList_Destory(SLIST *pHead)
{
    SLIST *tmp = NULL;
    if (pHead == NULL)
    {
        return -1;
    }

    while (pHead != NULL)
    {
        tmp = pHead->next;
        free(pHead);
        pHead = tmp;
    }
    return 0;
}

int SList_Reverse(SLIST *pHead)
{
    SLIST   *p = NULL; //前驱指针
    SLIST   *q = NULL; //当前指针
    SLIST   *t = NULL; //缓存的一个结点

    if (pHead==NULL || pHead->next == NULL ||pHead->next->next ==NULL )
    {
        return 0;
    }

    //初始化   //前驱结点
    p = pHead->next;
    q = pHead->next->next;

    //p = pHead;  //代码能兼容
    //q = pHead->next;

    //一个结点 一个结点的逆置
    while(q)
    {
        t = q->next; //缓冲后面的链表

        q->next = p;    //逆置

        p = q; //让p下移一个结点

        q = t;
    }

    //头节点 变成 尾部结点 后  置null
    pHead->next->next = NULL;
    pHead->next = p;  //

    return 0;
}
void main()
{
    int  ret = 0;

    SLIST *pHead = NULL;
    pHead = SList_Create();
    ret = SList_Print(pHead);

    ret = SList_NodeInsert(pHead, 20, 19);
    ret = SList_Print(pHead);

    ret = SList_NodeDel(pHead, 19);
    ret = SList_Print(pHead);

    ret =  SList_Reverse(pHead);
    ret = SList_Print(pHead);

    SList_Destory(pHead);

    printf("hello...\n");
    system("pause");
    return ;
}

链表是单向的,当前节点的位置保存在前驱节点的指针域,所以在插入的时候,要先将新节点的指针域指向当前节点(新节点插入在该节点之前),然后当前节点的前驱结点的指针域指向新节点。需要的辅助变量有三个:

pPre、pCur(指向要比较的节点)、pM(新增节点)

C语言链表_头结点_02

//顺序遍历单向动态链表
int  SList_Print(SLIST *pHead)
{
    SLIST *tmp = NULL; 

    if (pHead == NULL)
    {
        return -1;
    }

    tmp = pHead->next;//tmp指向第一个节点(不是头结点)
    printf("\nBegin\n");
    while (tmp)
    {
        printf("%d\n",tmp->data);
        tmp = tmp->next;//tmp永远指向要打印的当前节点
    }
    printf("\nEnd\n");
    return 0;
}

C语言链表_c语言_03

/*链表逆置*/
int SList_Reverse(SLIST * pHead)
{
    SLIST * pPre = NULL;//前驱节点
    SLIST * pCur = NULL;//当前节点
    SLIST * pNext = NULL;//后继节点

    /*合法性检测或者只有头节点或者只有一个节点和头结点*/
    if (pHead == NULL || pHead->next == NULL || pHead->next->next == NULL)
    {
        return -1;
    }

    /*初始化的时候将前驱结点指向第一个节点*/
    pPre = pHead->next;
    pCur = pHead->next->next;//当前节点指向第二个节点

    while (pCur)
    {
        pNext = pCur->next;//保存第三个节点的位置或者是NULL(链表尾)

        pCur->next = pPre;//当前节点的指针域指向前驱结点

        /*当前节点和前驱结点一起往后移动一个节点*/
        pPre = pCur;
        pCur = pNext;
    }

    pHead->next->next = NULL;//修正第一个节点的指针域指向NULL变成新的链表尾
    pHead->next = pPre;//修正头结点指向新链表的第一个节点(旧链表的最后一个节点)

    return 0;

}
typedef struct __node{
    int data;//数据域
    struct __node *next;//(指向自己结构体类型的)指针域
}SLIST;

/*创建链表(尾插法插入新节点)*/
SLIST *SList_Create()
{
    SLIST * pHead = NULL;//辅助指针变量之一,表示头结点
    SLIST * pCur = NULL;//让新节点变成当前节点的辅助指针变量
    SLIST * pM = NULL;//用于指向信malloc出的节点的辅助指针变量
    int data = 0;

    /*0.创建头结点*/
    pHead = (SLIST*)malloc(sizeof(SLIST));
    if (pHead == NULL)
    {
        return NULL;
    }
    pHead->data = 0;
    pHead->next = NULL;
    pCur = pHead;//pCur永远指向最后一个节点

    printf("\nplease input your data:");
    scanf("%d",&data);
    /*1.循环malloc出新节点*/
    while (data != 0)
    {
        pM = (SLIST*)malloc(sizeof(SLIST));
        if (pM == NULL)
        {
            return NULL;
        }
        pM->data = data;
        pM->next = NULL;

        /*2.新节点入链表*/
        pCur->next = pM;
        /*3.新节点变成当前节点*/
        pCur = pM;//pCur永远指向最后一个节点

        printf("\nplease input your data:");
        scanf("%d", &data);

    }
    return pHead;
}
/*在x之前插入y*/
int SList_NodeInsert(SLIST * pHead,int x,int y)
{

    SLIST * pPre = NULL;//辅助指针变量之一,表示要插入新节点的前驱结点
    SLIST * pCur = NULL;//表示要插入新节点的后继结点
    SLIST * pM = NULL;//用于指向新节点

    if (pHead == NULL)//合法性判断
    {
        return -1;
    }
    pPre = pHead;//初始化的时候让前驱结点指向头结点
    pCur = pHead->next;//初始化的时候让后继结点指向第一个节点(不是头结点)

    pM = (SLIST*)malloc(sizeof(SLIST));//为新节点开辟空间
    if (pM == NULL)
    {
        return -1;
    }
    /*初始化新节点*/
    pM->data = y;
    pM->next = NULL;

    while (pCur)//pCur指向要插入节点的后继节点,当pCur==NULL的时候表示遍历到链表尾
    {
        if (pCur->data == x){//没有到链表尾的时候判断该节点是否是要寻找的比较节点(这里是后继节点)
            break;
        }

        /*不满足条件时往后挪动辅助指针变量的位置*/
        pPre = pCur;
        pCur = pCur->next;
    }

    /*不管原链表存不存在X节点,都会将新节点插入链表,不存在的时候插入到链表尾,存在的时候插入到X节点前面*/
    pM->next = pCur;
    pPre->next = pM;


    return 0;
}
/*删除链表中数据域为y的节点*/
int SList_NodeDelete(SLIST * pHead, int y)
{   
    SLIST *pPre = NULL;//指向要删除节点的前驱结点
    SLIST *pCur = NULL;//指向要删除的节点或者直到链表尾

    if (pHead == NULL)//合法性检测
    {
        return -1;
    }

    /*初始化的时候前驱结点指向头结点,要删除节点指向第一个非头结点的节点即使是空指针(即链表除了头结点没有任何元素)*/
    pPre = pHead;
    pCur = pHead->next;

    while (pCur)//只要当前节点不是空指针(即没有到链表尾)
    {
        if (pCur->data == y)//满足条件不在移动辅助指针变量的指向
        {
            break;
        }
        /*不满足条件时往后挪动辅助指针变量的位置*/
        pPre = pCur;
        pCur = pCur->next;

    }

    if (pCur == NULL)//寻找到链表尾没有发现要删除的节点
    {
        printf("cant find the node of y\n");
        return -2;
    }

    pPre->next = pCur->next;//删除节点
    if (pCur != NULL)
    {
        free(pCur);//内存回收
        pCur = NULL;//避免野指针
    }


    return 0;
}
/*销毁链表*/
int SList_Destroy(SLIST ** pHead)
{

    SLIST *pCur = NULL;//指向要销毁的当前节点
    SLIST *pTmp = NULL;//用于缓存要销毁的节点的数据,否则一旦销毁以后找不到后继节点,实际上就是指向后一个节点

    if (NULL == pHead)
    {
        return -1;
    }
    if (NULL == *pHead)
    {
        return -1;
    }
    pCur = (SLIST *)(*pHead);//初始化的时候将pCur指向头结点

    while (pCur)
    {
        pTmp = pCur->next;//缓存上一个节点的数据以便找到后继节点
        free(pCur);
        pCur = pTmp;//将pCur指向后继节点
    }
    *pHead = NULL;//避免野指针

    return 0;
}


标签:SLIST,C语言,next,链表,pCur,pHead,NULL,节点
From: https://blog.51cto.com/u_16147764/6397248

相关文章

  • 链表归并排序
    输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。/*structListNode{intval;structListNode*next;ListNode(intx):val(x),next(NULL){}};*/classSolution{public:ListNode*Merge(......
  • 链表的相关操作
    链表的相关操作#pragmaonce//编程的接口(API)//*.h文件中一般会放:类型的定义,函数的声明,全局变量#include<stdbool.h>typedefstructnode{ intval; structnode*next;}Node;typedefstruct{ Node*head; Node*tail; intsize;}List;List*create_......
  • 单元测试及C语言的几个例子
     一、单元测试介绍单元测试是软件开发中的一种测试方式,它主要是对代码中最小可测试单元进行检查和验证。通常来说,单元测试的实施应该在整个软件开发周期的早期就开始,最好是在代码编写过程中就边写边测试,以及在执行集成和系统测试之前启动。下面是单元测试的详解:单元测试的目的:单元......
  • python 合并k个有序链表
     fromheapqimportheappush,heappopclassSolution:defmergeKLists(self,lists):q=[]fori,headinenumerate(lists):ifhead:heappush(q,(head.val,i,head))node=dummy=ListNode(0)......
  • 合并两个有序链表
     将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  经典算法,采用递归法就行了,别的算法也有,但有限考虑能想得到的。每次将两个头节点值较小的链表 l1 和 l2 中的头结点合并,并返回合并后的头结点,递归地进行下去,直到......
  • Linux系统下C语言的编程技巧
    Linux系统能够为人们提供更加安全实用的效果,保证计算机系统能够稳定的运行。利用Linux系统下首先要进行C语言的编程,掌握编程的技巧能够更好的发挥计算机的作用。如何掌握Linux系统下计算机C语言的编程技巧是计算机发展的关键要素。本文对Linux系统下计算机C语言的编程技巧进行相......
  • 初级数据结构--单链表
    继昨天终于明白了成功截图typedefstructLNode{ intdata; structLNode*next;}LNode;boolIsitList(LNode**Head){ *Head=(LNode*)malloc(sizeof(LNode)); if(!*Head) returnfalse; (*Head)->next=NULL; returntrue;}voidListInsert(LNode*L,intval......
  • 2.单向链表
    1.为什么需要链表?  链表是一种灵活的数据结构,它允许在内存中动态地存储和操作元素。以下是一些需要使用链表的原因:1.动态数组的缺点:数组的大小是在程序运行时固定的,如果需要添加或删除元素,就需要重新分配内存并复制数据。这会导致大量的内存浪费和性能问题。而链表可以动态地......
  • c语言值得注意的知识
    1.说明下列每对scanf格式串是否等价?如果不等价,请指出它们的差异。(c)"%f"与"%f "。在`scanf`函数中,`"%f"`和`"%f"`这两种格式的区别在于后面的空格。1.`scanf("%f",&variable);`这种情况下,`scanf`会读取并解析用户输入的浮点数,然后将解析的值存入`variable`中。......
  • 线性链表的基本操作
    线性链表常见的操作:插入,删除,查找等等。以下采用尾插法建立的线性链表。#include<iostream>#include<string.h>#include<stdio.h>usingnamespacestd;structnode{intval;node*next;};node*head,*p,*q;voidInit(){head=newnode();q=h......