链表

    科技2022-08-05  92

    链表就是一个元素个数可以实时变大/变小的数组 链表就是被锁链链接起来的表。这里的表指的是一个一个的节点,节点内的一些内存可以用来存储数据;这里的锁链指的是链接各个表的方式,C语言中用指针来链接2块内存

    链表是由若干个节点组成的,节点由有效数据和指针组成(节点结构完全类似),有效数据用来存储信息完成任务的,指针区域用于指向链表的下一个节点而构成链表

    总结 链表本质上就是用来解决数组的大小不能动态扩展的问题,所以链表其实就是当数组用的。 链表就是用来存储数据的,链表用来存数据相对于数组来说有点就是灵活性,需要多少个动态分配多少个,不占用额外内存。

    单链表的实现 定义的struct node只是一个机构体,本身没有变量生成,也不占用内存。结构体定义相当于为链表节点定义了一个模板,但是还没有一个节点,将来在实际创建链表时需要一个节点时用这个模板来赋值一个即可 链表的内存需求比较灵活,只能使用堆内存:malloc申请堆内存,大小为一个节点大小,清理申请到的堆内存,把申请到的堆内存当做一个新节点,填充新节点的有效数据和指定区域

    #include<stdio.h> //构建一个链表的节点 struct node { int data; //有效数据 struct node *pnext; //指向下一个节点的指针 }; int main(void) { //定义头指针 struct node *header = NULL; //创建一个链表节点 struct node *p=(struct node*)(malloc(sizeof(struct node)); if(NULL==p) { printf("malloc error.\n"); return -1; } //清理申请到的堆内存 bzero(p,sizeof(struct ndoe)); //填充节点 p->data = 1; p->pnext = NULL; //下一个节点不知道是啥,所以暂时指向NULL (下一个节点的首地址) header = p; //p是第一个节点的首地址,p赋值给header 相当于将头指针和首地址链接起来 return 0 ; };

    头指针 header 只是一个指针,指向第一个节点的首地址,只占四个字节,头指针的类型是 struct node *

    #include<stdio.h> #include<stdlib.h> #include<strings.h> //构建一个链表的节点 struct node { int data; //有效数据 struct node *pnext; //指向下一个节点的指针 }; int main(void) { //定义头指针 struct node *header = NULL; //创建一个链表节点` struct node *p1=(struct node*)(malloc(sizeof(struct node)); if(NULL==p1) { printf("malloc error.\n"); return -1; } //清理申请到的堆内存 bzero(p1,sizeof(struct ndoe)); //填充节点 p1->data = 2; p1->pnext = NULL; //下一个节点不知道是啥,所以暂时指向NULL (下一个节点的首地址) header = p1; //p是第一个节点的首地址,p赋值给header 相当于将头指针和首地址链接起来 //创建一个链表节点 struct node *p2=(struct node*)(malloc(sizeof(struct node)); if(NULL==p2) { printf("malloc error.\n"); return -1; } //清理申请到的堆内存 bzero(p2,sizeof(struct ndoe)); //填充节点 p2->data = 3; p2->pnext = NULL; //下一个节点不知道是啥,所以暂时指向NULL (下一个节点的首地址) p1->pnext = p2; //创建一个链表节点 struct node *p3=(struct node*)(malloc(sizeof(struct node)); if(NULL==p3) { printf("malloc error.\n"); return -1; } //清理申请到的堆内存 bzero(p3,sizeof(struct ndoe)); //填充节点 p3->data = 3; p2->pnext=p3; p3->pnext = NULL; return 0 ; };

    访问链表第一个节点的有效数据 printf(“node data %d\n”,header->data); //等同于 p1->data 访问链表第二个节点的有效数据 printf(“node data %d\n”,header->pnext->data); //headerp1 p1->pnext->p2 p2->data 访问链表第三个节点的有效数据 printf(“node data %d\n”,header->pnext->pnext->data); //headerp1 p1->pnext->p2 p2->pnext->p3 p3_data

    只能通过头指针来访问链表里面的数据,不能直接用各自的指针,因为在程序中我们保存链表是不会保存各个节点的指针的。 前一个节点内部的pnext指针能帮助我们找到下一个节点 单链表算法之插入节点 将创建节点的代码封装成一个函数

    简单理解版:

    #include<stdio.h> #include<stdlib.h> #include<strings.h> //构建一个链表的节点 struct node { int data; //有效数据 struct node *pnext; //指向下一个节点的指针 }; //作用:创建一个链表节点 返回值:struct node * ,指针指向我们本函数新创建的一个节点的首地址 struct node *creat_node(int data) { struct node *p1=(struct node *)malloc(sizeof(struct node)); if(NULL=p1) { printf("error\n"); return NULL; } bzero(p1,sizeof(struct node)); p1->data=data; p1->pnext=NULL; return p1; } struct node *creat_node2(int data) { struct node *p2=(struct node*)malloc(sizeof(struct node)); if(NULL==p2) { printf("malloc error.\n"); return NULL; } bzero(p2,sizeof(struct ndoe)); //填充节点 p2->data = 2; p2->pnext = NULL; //下一个节点不知道是啥,所以暂时指向NULL (下一个节点的首地址) return p2; } struct node *creat_node3(int data) { struct node *p3=(struct node*)malloc(sizeof(struct node)); if(NULL==p3) { printf("malloc error.\n"); return NULL; } //清理申请到的堆内存 bzero(p3,sizeof(struct ndoe)); //填充节点 p3->data = data; p3->pnext = NULL; return p3; } int main(void) { //定义头指针 struct node *header = NULL; header = creat_node(1); //等同于 header=p1 header->pnext=creat_node2(2); header->pnext->pnext=creat_node3(3); return 0 ; }

    正常版

    #include<stdio.h> #include<stdlib.h> #include<strings.h> //构建一个链表的节点 struct node { int data; //有效数据 struct node *pnext; //指向下一个节点的指针 }; struct node *creat_node(int data) { struct node *p=(struct node *)malloc(sizeof(struct node)); if(NULL=p) { printf("error\n"); return NULL; } bzero(p,sizeof(struct node)); p->data=data; p->pnext=NULL; return p; } int main(void) { struct node *header=NULL; header=creat_node(1); header->pnext=creat_node(2); header->pnext->pnext=creat_node(3); return 0; }

    在链表尾部插入新节点

    #include<stdio.h> #include<stdlib.h> #include<strings.h> //构建一个链表的节点 struct node { int data; //有效数据 struct node *pnext; //指向下一个节点的指针 }; struct node *creat_node(int data) { struct node *p=(struct node *)malloc(sizeof(struct node)); if(NULL=p) { printf("error\n"); return NULL; } bzero(p,sizeof(struct node)); p->data=data; p->pnext=NULL; return p; } void insert_tail(struct node *ph,struct node *new) { //先找到链表中最后一个节点 struct node *p = ph; while (NULL !=p->pnext) { p=p->pnext; } //将最后一个插入尾部 p->pnext = new; } int main(void) { // struct node *header=NULL; struct node *header = creat_node(1); insert_tail(pHeader, create_node(2)); insert_tail(pHeader, create_node(3)); insert_tail(pHeader, create_node(4)); header=creat_node(2); header->pnext=creat_node(3); header->pnext->pnext=creat_node(4); return 0; }

    在链表头部插入新节点

    #include<stdio.h> #include<stdlib.h> #include<strings.h> //构建一个链表的节点 struct node { int data; //有效数据 struct node *pnext; //指向下一个节点的指针 }; struct node *creat_node(int data) { struct node *p=(struct node *)malloc(sizeof(struct node)); if(NULL=p) { printf("error\n"); return NULL; } bzero(p,sizeof(struct node)); p->data=data; p->pnext=NULL; return p; } void insert_head(struct node *ph,struct node *new) { //新节点的pnext指向原来的第一个节点 new->pnext=ph->pnext; //头节点的next指向新节点地址 ph->pnext=new; //头节点的计数+1 ph->data +=1; } int main(void) { struct node *header = creat_node(0); insert_head(pHeader, create_node(1)); insert_head(pHeader, create_node(2)); insert_head(pHeader, create_node(3)); return 0; }
    Processed: 0.010, SQL: 8