c语言单链表的创建
C++链表的创建与操作
C++链表的创建与操作我们知道,数组式计算机根据事先定义好的数组类型与长度自动为其分配一连续的存储单元,相同数组的位置和距离都是固定的,也就是说,任何一个数组元素的地址都可一个简单的公式计算出来,因此这种结构可以有效的对数组元素进行随机访问。
但若对数组元素进行插入和删除操作,则会引起大量数据的移动,从而使简单的数据处理变得非常复杂,低效。
为了能有效地解决这些问题,一种称为“链表”的数据结构得到了广泛应用。
1.链表概述链表是一种动态数据结构,他的特点是用一组任意的存储单元(可以是连续的,也可以是不连续的)存放数据元素。
链表中每一个元素成为“结点”,每一个结点都是由数据域和指针域组成的,每个结点中的指针域指向下一个结点。
Head是“头指针”,表示链表的开始,用来指向第一个结点,而最后一个指针的指针域为NULL(空地址),表示链表的结束。
可以看出链表结构必须利用指针才能实现,即一个结点中必须包含一个指针变量,用来存放下一个结点的地址。
实际上,链表中的每个结点可以用若干个数据和若干个指针。
结点中只有一个指针的链表称为单链表,这是最简单的链表结构。
再c++中实现一个单链表结构比较简单。
例如,可定义单链表结构的最简单形式如下struct Node{int Data;Node *next;};这里用到了结构体类型。
其中,*next是指针域,用来指向该结点的下一个结点;Data是一个整形变量,用来存放结点中的数据。
当然,Data可以是任何数据类型,包括结构体类型或类类型。
在此基础上,我们在定义一个链表类list,其中包含链表结点的插入,删除,输出等功能的成员函数。
class list{Node *head;public:list(){head=NULL;}void insertlist(int aDate,int bDate); //链表结点的插入void Deletelist(int aDate); //链表结点的删除void Outputlist(); //链表结点的输出Node*Gethead(){return head;}};2.链表结点的访问由于链表中的各个结点是由指针链接在一起的,其存储单元文笔是连续的,因此,对其中任意结点的地址无法向数组一样,用一个简单的公式计算出来,进行随机访问。
[转载整理]C语言链表实例
[转载整理]C语⾔链表实例 C语⾔链表有单链表、双向链表、循环链表。
单链表由数据域和指针域组成,数据域存放数据,指针域存放该数据类型的指针便于找到下⼀个节点。
双链表则含有头指针域、数据域和尾指针域,域单链表不同,双链表可以从后⼀个节点找到前⼀个节点,⼆单链表则不⾏。
循环链表就是在单链表的基础上,将头结点的地址指针存放在最后⼀个节点的指针域⾥以,此形成循环。
此外还有双向循环链表,它同时具有双向链表和循环链表的功能。
单链表如:链表节点的数据结构定义struct node{int num;struct node *p;} ;在此链表节点的定义中,除⼀个整型的成员外,成员p是指向与节点类型完全相同的指针。
※在链表节点的数据结构中,⾮常特殊的⼀点就是结构体内的指针域的数据类型使⽤了未定义成功的数据类型。
这是在C中唯⼀规定可以先使⽤后定义的数据结构。
链表实例代码:1// 原⽂地址 /wireless-dragon/p/5170565.html2 #include<stdio.h>3 #include<stdlib.h>4 #include<string.h>56 typedef int elemType;//定义存⼊的数据的类型可以是int char78 typedef struct NODE{ //定义链表的结构类型9 elemType element;10struct NODE *next;11 }Node;1213/************************************************************************/14/* 以下是关于线性表链接存储(单链表)操作的19种算法 */1516/* 1.初始化线性表,即置单链表的表头指针为空 */17/* 2.创建线性表,此函数输⼊负数终⽌读取数据*/18/* 3.打印链表,链表的遍历*/19/* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为⼀个空表 */20/* 5.返回单链表的长度 */21/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */22/* 7.返回单链表中第pos个结点中的元素,若pos超出范围,则停⽌程序运⾏ */23/* 8.从单链表中查找具有给定值x的第⼀个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */24/* 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 */25/* 10.向单链表的表头插⼊⼀个元素 */26/* 11.向单链表的末尾添加⼀个元素 */27/* 12.向单链表中第pos个结点位置插⼊元素为x的结点,若插⼊成功返回1,否则返回0 */28/* 13.向有序单链表中插⼊元素x结点,使得插⼊后仍然有序 */29/* 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停⽌程序运⾏ */30/* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停⽌程序运⾏ */31/* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停⽌程序运⾏ */32/* 17.从单链表中删除值为x的第⼀个结点,若删除成功则返回1,否则返回0 */33/* 18.交换2个元素的位置 */34/* 19.将线性表进⾏冒排序 */35363738/*注意检查分配到的动态内存是否为空*/3940414243/* 1.初始化线性表,即置单链表的表头指针为空 */44void initList(Node **pNode)45 {46 *pNode=NULL;47 printf("initList函数执⾏,初始化成功\n");48 }4950/* 2.创建线性表,此函数输⼊负数终⽌读取数据*/51 Node *creatList(Node *pHead)52 {53 Node *p1,*p2;54 p1=p2=(Node *)malloc(sizeof(Node));55if(p1 == NULL || p2 ==NULL)57 printf("内存分配失败\n");58 exit(0);59 }60 memset(p1,0,sizeof(Node));6162 scanf("%d",&p1->element);63 p1->next=NULL;6465while(p1->element >0) //输⼊的值⼤于0则继续,否则停⽌66 {67if(pHead == NULL)//空表,接⼊表头68 {69 pHead=p1;70 }71else72 {73 p2->next=p1;74 }7576 p2=p1;77 p1=(Node *)malloc(sizeof(Node));7879if(p1==NULL||p2==NULL)80 {81 printf("内存分配失败\n");82 exit(0);83 }84 memset(p1,0,sizeof(Node));85 scanf("%d",&p1->element);86 p1->next=NULL;87 }88 printf("CreatList函数执⾏,链表创建成功\n");89return pHead;90 }9192/* 3.打印链表,链表的遍历*/93void printList(Node *pHead)94 {95if(NULL==pHead)96 {97 printf("PrintList函数执⾏,链表为空\n");98 }99else100 {101while(NULL!=pHead)102 {103 printf("%d\n",pHead->element);104 pHead=pHead->next;105 }106 }107108 }109110111/* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为⼀个空表 */ 112void clearList(Node *pHead)113 {114 Node *pNext;115116if(pHead==NULL)117 {118 printf("clearList函数执⾏,链表为空\n");119return;120 }121while(pHead->next!=NULL)122 {123 pNext=pHead->next;124free(pHead);125 pHead=pNext;126 }127 printf("clearList函数执⾏,链表已经清除!\n");128129 }130131/* 5.返回链表的长度*/132int sizeList(Node *pHead)133 {134int size=0;135136while(pHead!=NULL)137 {138 size++;139 pHead=pHead->next;141 printf("sizelist函数执⾏,链表长度为%d\n",size);142return size;143 }144145/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */146int isEmptyList(Node *pHead)147 {148if(pHead==NULL)149 {150 printf("isEmptylist函数执⾏,链表为空!\n");151return1;152 }153154else155 printf("isEmptylist函数执⾏,链表⾮空!\n");156return0;157158 }159160/* 7.返回链表中第post节点的数据,若post超出范围,则停⽌程序运⾏*/161int getElement(Node *pHead,int pos)162 {163int i=0;164if(pos<1)165 {166 printf("getElement函数执⾏,pos值⾮法!");167return0;168 }169if(pHead==NULL)170 {171 printf("getElement函数执⾏,链表为空!");172 }173174while (pHead!=NULL)175 {176 ++i;177if(i==pos)178 {179break;180 }181 pHead=pHead->next;182 }183if(i<pos)184 {185 printf("getElement函数执⾏,pos值超出链表长度\n");186return0;187 }188 printf("getElement函数执⾏,位置%d中的元素为%d\n",pos,pHead->element);189190return1;191 }192193//8.从单⼀链表中查找具有给定值x的第⼀个元素,若查找成功后,返回该节点data域的存储位置,否则返回NULL 194 elemType *getElemAddr(Node *pHead,elemType x)195 {196if(NULL==pHead)197 {198 printf("getEleAddr函数执⾏,链表为空");199return NULL;200 }201if(x<0)202 {203 printf("getEleAddr函数执⾏,给定值x不合法\n");204return NULL;205 }206while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素207 {208 pHead=pHead->next;209 }210if(pHead->element!=x)211 {212 printf("getElemAddr函数执⾏,在链表中没有找到x值\n");213return NULL;214 }215else216 {217 printf("getElemAddr函数执⾏,元素%d的地址为0x%x\n",x,&(pHead->element));218 }219return &(pHead->element);220221 }222223224/*9.修改链表中第pos个点X的值,如果修改成功,则返回1,否则返回0*/225int modifyElem(Node *pNode,int pos,elemType x)226 {227 Node *pHead;228 pHead=pNode;229int i=0;230if(NULL==pHead)231 {232 printf("modifyElem函数执⾏,链表为空\n");233return0;234 }235236if(pos<1)237 {238 printf("modifyElem函数执⾏,pos值⾮法\n");239return0;240 }241242while(pHead!= NULL)243 {244 ++i;245if(i==pos)246 {247break;248 }249 pHead=pHead->next;250 }251252if(i<pos)253 {254 printf("modifyElem函数执⾏,pos值超出链表长度\n");255return0;256 }257 pNode=pHead;258 pNode->element=x;259 printf("modifyElem函数执⾏,修改第%d点的元素为%d\n",pos,x);260261return1;262263 }264265/* 10.向单链表的表头插⼊⼀个元素 */266int insertHeadList(Node **pNode,elemType insertElem)267 {268 Node *pInsert;269 pInsert=(Node *)malloc(sizeof(Node));270if(pInsert==NULL) exit(1);271 memset(pInsert,0,sizeof(Node));272 pInsert->element=insertElem;273 pInsert->next=*pNode;274 *pNode=pInsert;275 printf("insertHeadList函数执⾏,向表头插⼊元素%d成功\n",insertElem);276return1;277 }278279/* 11.向单链表的末尾添加⼀个元素 */280int insertLastList(Node *pNode,elemType insertElem)281 {282 Node *pInsert;283 Node *pHead;284 Node *pTmp;285286 pHead=pNode;287 pTmp=pHead;288 pInsert=(Node *)malloc(sizeof(Node));289if(pInsert==NULL) exit(1);290 memset(pInsert,0,sizeof(Node));291 pInsert->element=insertElem;292 pInsert->next=NULL;293while(pHead->next!=NULL)294 {295 pHead=pHead->next;296 }297 pHead->next=pInsert;298 printf("insertLastList函数执⾏,向表尾插⼊元素%d成功!\n",insertElem);299return1;300 }301302/* 12.向单链表中第pos个结点位置插⼊元素为x的结点,若插⼊成功返回1,否则返回0*/ 303int isAddPos(Node *pNode,int pos,elemType x)304 {305 Node *pHead;306 pHead=pNode;307 Node *pTmp;308int i=0;309310if(NULL==pHead)311 {312 printf("AddPos函数执⾏,链表为空\n");313return0;314 }315316if(pos<1)317 {318 printf("AddPos函数执⾏,pos值⾮法\n");319return0;320 }321322while(pHead!=NULL)323 {324 ++i;325if(i==pos)326break;327 pHead=pHead->next;328 }329330if(i<pos)331 {332 printf("AddPos函数执⾏,pos值超出链表长度\n");333return0;334 }335336 pTmp=(Node *)malloc(sizeof(Node));337if(pTmp==NULL) exit(1);338 memset(pTmp,0,sizeof(Node));339 pTmp->next=pHead->next;340 pHead->next=pTmp;341 pTmp->element=x;342343 printf("AddPos函数执⾏成功,向节点%d后插⼊数值%d\n",pos,x); 344return1;345 }346347/* 13.向有序单链表中插⼊元素x结点,使得插⼊后仍然有序 */348int OrrderList(Node *pNode,elemType x)349 {350//注意如果此数值要排到⾏尾要修改本代码351 Node *pHead;352 pHead=pNode;353 Node *pTmp;354355if(NULL==pHead)356 {357 printf("OrrderList函数执⾏,链表为空\n");358return0;359 }360361if(x<1)362 {363 printf("OrrderList函数执⾏,x值⾮法\n");364return0;365 }366367while(pHead!=NULL)368 {369if((pHead->element)>=x)370break;371 pHead=pHead->next;372 }373374375if(pHead==NULL)376 {377 printf("OrrderList函数查找完毕,该函数中没有该值\n");378return0;379 }380381382 pTmp=(Node *)malloc(sizeof(Node));383if(pTmp==NULL) exit(1);384 memset(pTmp,0,sizeof(Node));385 pTmp->next=pHead->next;386 pHead->next=pTmp;387 pTmp->element=x;388389 printf("OrrderList函数成功插⼊数值%d\n",x);390return1;391 }392393/*14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停⽌程序运⾏*/ 394int DelHeadList(Node **pList)395 {396 Node *pHead;397 pHead=*pList;398if(pHead!=NULL)399 printf("DelHeadList函数执⾏,函数⾸元素为%d删除成功\n",pHead->element); 400else401 {402 printf("DelHeadList函数执⾏,链表为空!");403return0;404 }405 *pList=pHead->next;406return1;407 }408409/* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停⽌程序运⾏ */410int DelLastList(Node *pNode)411 {412 Node *pHead;413 Node *pTmp;414415 pHead=pNode;416while(pHead->next!=NULL)417 {418 pTmp=pHead;419 pHead=pHead->next;420 }421 printf("链表尾删除元素%d成功!\n",pHead->element);422free(pHead);423 pTmp->next=NULL;424return1;425 }426427/* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停⽌程序运⾏ */ 428int DelPos(Node *pNode,int pos)429 {430 Node *pHead;431 pHead=pNode;432 Node *pTmp;433434int i=0;435436if(NULL==pHead)437 {438 printf("DelPos函数执⾏,链表为空\n");439return0;440 }441442if(pos<1)443 {444 printf("DelPos函数执⾏,pos值⾮法\n");445return0;446 }447448while(pHead!=NULL)449 {450 ++i;451if(i==pos)452break;453 pTmp=pHead;454 pHead=pHead->next;455 }456457if(i<pos)458 {459 printf("DelPos函数执⾏,pos值超出链表长度\n");460return0;461 }462 printf("DelPos函数执⾏成功,节点%d删除数值%d\n",pos,pHead->element); 463 pTmp->next=pHead->next;464free(pHead);465return1;466 }467468/* 17.从单链表中删除值为x的第⼀个结点,若删除成功则返回1,否则返回0 */469int Delx(Node **pNode,int x)470 {471 Node *pHead;472 Node *pTmp;473 pHead=*pNode;474int i=0;475476if(NULL==pHead)477 {478 printf("Delx函数执⾏,链表为空");479return0;480 }481if(x<0)482 {483 printf("Delx函数执⾏,给定值x不合法\n");484return0;485 }486while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素487 {488 ++i;489 pTmp=pHead;490 pHead=pHead->next;491 }492if(pHead->element!=x)493 {494 printf("Delx函数执⾏,在链表中没有找到x值\n");495return0;496 }497if((i==0)&&(NULL!=pHead->next))498 {499 printf("Delx函数执⾏,在链表⾸部找到此元素,此元素已经被删除\n");500 *pNode=pHead->next;501free(pHead);502return1;503 }504 printf("Delx函数执⾏,⾸个为%d元素被删除\n",x);505 pTmp->next=pHead->next;506free(pHead);507return1;508 }509510/* 18.交换2个元素的位置 */511int exchange2pos(Node *pNode,int pos1,int pos2)512 {513 Node *pHead;514int *pTmp;515int *pInsert;516int a;517int i=0;518519if(pos1<1||pos2<1)520 {521 printf("DelPos函数执⾏,pos值⾮法\n");522return0;523 }524525 pHead=pNode;526while(pHead!=NULL)527 {528 ++i;529if(i==pos1)530break;531 pHead=pHead->next;532 }533534if(i<pos1)535 {536 printf("DelPos函数执⾏,pos1值超出链表长度\n");537return0;538 }539540 pTmp=&(pHead->element);541 i=0;542 pHead=pNode;543while(pHead!=NULL)544 {545 ++i;546if(i==pos2)547break;548 pHead=pHead->next;549 }550551if(i<pos2)552 {553 printf("DelPos函数执⾏,pos2值超出链表长度\n");554return0;555 }556557 pInsert=&(pHead->element);558 a=*pTmp;559 *pTmp=*pInsert;560 *pInsert=a;561562 printf("DelPos函数执⾏,交换第%d个和第%d个pos点的值\n",pos1,pos2); 563return1;564 }565566int swap(int *p1,int *p2)567 {568int a;569if(*p1>*p2)570 {571 a=*p1;572 *p1=*p2;573 *p2=a;574 }575return0;576 }577578/* 19.将线性表进⾏冒泡排序 */579int Arrange(Node *pNode)580 {581 Node *pHead;582 pHead=pNode;583584int a=0,i,j;585586if(NULL==pHead)587 {588 printf("Arrange函数执⾏,链表为空\n");589return0;590 }591592while(pHead!=NULL)593 {594 ++a;595 pHead=pHead->next;596 }597598 pHead=pNode;599for(i=0;i<a-1;i++)600 {601for(j=1;j<a-i;j++)602 {603 swap(&(pHead->element),&(pHead->next->element));604 pHead=pHead->next;605 }606 pHead=pNode;607 }608 printf("Arrange函数执⾏,链表排序完毕!\n");609return0;610 }611612int main()613 {614 Node *pList=NULL;615int length=0;616617 elemType posElem;618619 initList(&pList);620 printList(pList);621622 pList=creatList(pList);623 printList(pList);624625 sizeList(pList);626 printList(pList);627628 isEmptyList(pList);629630631 posElem=getElement(pList,3);632 printList(pList);633634 getElemAddr(pList,5);635636 modifyElem(pList,4,1);637 printList(pList);638639 insertHeadList(&pList,5);640 printList(pList);641642 insertLastList(pList,10);643 printList(pList);644645 isAddPos(pList,4,5); 646 printList(pList);647648 OrrderList(pList,6);649 printList(pList);650651 DelHeadList(&pList); 652 printList(pList);653654 DelLastList(pList);655 printList(pList);656657 DelPos(pList,5);658 printList(pList);659660 Delx(&pList,5);661 printList(pList);662663 exchange2pos(pList,2,5); 664 printList(pList);665666 Arrange(pList);667 printList(pList);668669 clearList(pList);670return0;671 }。
c语言链表的创建方法
c语言链表的创建方法在C语言中,链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个值和一个指向下一个节点的指针。
链表可以动态地添加或删除节点,因此在许多应用程序中被广泛使用。
链表的创建方法大致可以分为以下几个步骤:1. 定义一个节点结构体链表的节点通常包含一个值和一个指针,指针指向下一个节点。
因此,我们需要定义一个结构体来表示节点:```struct Node {int data;struct Node* next;};```其中,`data`表示节点的值,`next`表示指向下一个节点的指针。
2. 创建第一个节点创建第一个节点时,我们需要先分配一段内存,然后将节点的值和指针都赋值为NULL:```struct Node* head = NULL;head = (struct Node*)malloc(sizeof(struct Node));head->data = 1;head->next = NULL;```这里我们使用了`malloc`函数来分配内存,并将返回的指针强制转换为`struct Node*`类型,然后将节点的值和指针赋值为1和NULL。
3. 添加新节点添加新节点时,我们需要先找到链表的末尾,然后在末尾添加新节点:```struct Node* newNode = NULL;newNode = (struct Node*)malloc(sizeof(struct Node));newNode->data = 2;newNode->next = NULL;struct Node* current = head;while (current->next != NULL) {current = current->next;}current->next = newNode;```这里我们定义了一个新节点`newNode`,然后遍历链表找到末尾节点,将末尾节点的指针指向新节点。
数据结构单链表实验报告
数据结构单链表实验报告一、实验目的1、深入理解单链表的数据结构及其基本操作。
2、掌握单链表的创建、插入、删除、查找等操作的实现方法。
3、通过实际编程,提高对数据结构和算法的理解和应用能力。
二、实验环境1、操作系统:Windows 102、编程语言:C 语言3、开发工具:Visual Studio 2019三、实验原理单链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据域和指针域。
指针域用于指向下一个节点,从而形成链表的链式结构。
单链表的基本操作包括:1、创建链表:通过动态分配内存创建链表的头节点,并初始化链表为空。
2、插入节点:可以在链表的头部、尾部或指定位置插入新的节点。
3、删除节点:根据给定的条件删除链表中的节点。
4、查找节点:在链表中查找满足特定条件的节点。
四、实验内容(一)单链表的创建```cinclude <stdioh>include <stdlibh>//定义链表节点结构体typedef struct Node {int data;struct Node next;} Node;//创建单链表Node createList(){Node head =(Node)malloc(sizeof(Node));if (head == NULL) {printf("内存分配失败!\n");return NULL;}head>data = 0;head>next = NULL;return head;}int main(){Node list = createList();//后续操作return 0;}```在创建单链表时,首先为头节点分配内存空间。
若内存分配失败,则提示错误信息并返回`NULL`。
成功分配内存后,初始化头节点的数据域和指针域。
(二)单链表的插入操作插入操作分为三种情况:头部插入、尾部插入和指定位置插入。
1、头部插入```cvoid insertAtHead(Node head, int data) {Node newNode =(Node)malloc(sizeof(Node));if (newNode == NULL) {printf("内存分配失败!\n");return;}newNode>data = data;newNode>next = head>next;head>next = newNode;}```头部插入时,创建新节点,将新节点的数据域赋值,并将其指针域指向原头节点的下一个节点,然后更新头节点的指针域指向新节点。
创建单链表
q=print(l);
}
else if(k==2)
{
cout<<"请输入您要查找的数据值:";
cin>>ch;
p=find(l,ch);
q=print(l);
}
else if(k==3)
{
cout<<"请输入您要删除的数据的位置:";
? 单链表的打印
? 单链表的插入
? 单链表的删除
? 单链表的查询
三实验步骤
? 程序设计规划(实现的功能、分几个模块、子函数)
? 编写单链表创建子函数
? 编写单链表打印子函数
? 编写单链表插入子函数
? 编写单链表删除子函数
? 编写单链表查询子函数
? 编写主函数Main(),通过功能菜单调用子函数
cin>>i;
p=del(l,i);
q=print(l);
}
else if(k==4)
{ p=add(l);
q=print(l);
}
else if(k==0)
;
else
{cout<<"输入错误!"<<endl;
q=print(l);}
return l;
//l=head;
q=print(l);
return 0;
}
c语言的
#include <stdio.h>
#include <malloc.h>
#define N 8
数据结构c语言版创建单链表的代码
数据结构c语言版创建单链表的代码单链表作为常用的线性结构之一,常常用于解决以链式方式存储数据的问题。
创建单链表需要掌握一些基础的数据结构知识以及对C语言的熟练运用。
接下来,本文将分步骤地阐述数据结构C语言版创建单链表的代码。
第一步,定义单链表结构体并定义节点类型。
在C语言中,我们可以通过结构体的方式定义单链表,其中结构体中包含两个成员变量,分别为存储数据的data和指向下一个节点的指针next。
对于节点类型,我们可以使用typedef对节点类型进行定义,例如:```struct ListNode {int data;struct ListNode *next;};typedef struct ListNode ListNode;```在以上代码中,我们首先定义了一个结构体ListNode作为单链表的元素类型,其中包含存储数据的data和指向下一个元素的指针next。
接着我们使用typedef将结构体ListNode定义为仿函数ListNode,从而使其更加方便使用。
第二步,初始化单链表。
在创建单链表之前,我们需要先将单链表的头指针初始化为NULL,表示当前链表为空。
具体代码如下:```ListNode *createLinkedList() {ListNode *head = NULL;return head;}```以上代码中,函数createLinkedList用于创建并初始化单链表,其中head表示单链表头指针,我们将其初始化为NULL。
第三步,向单链表中添加元素。
在单链表中添加元素需要借助于指针的指向关系。
具体来说,我们需要先创建新的节点,将其数据添加到节点中,然后将新节点的next指针指向之前的头节点,最后将头指针指向新节点。
具体过程如下:```ListNode *addListNode(ListNode **head, int val) {ListNode *newNode = (ListNode *)malloc(sizeof(ListNode)); newNode->data = val;newNode->next = *head;*head = newNode;return *head;}```在以上代码中,函数addListNode接收一个指向头指针的指针head,以及需要添加的元素值val。
数据结构C语言版 线性表的单链表存储结构表示和实现
#include 〈stdio.h>#include <malloc。
h>#include 〈stdlib.h>/*数据结构C语言版线性表的单链表存储结构表示和实现P28—31编译环境:Dev-C++ 4。
9。
9。
2日期:2011年2月10日*/typedef int ElemType;// 线性表的单链表存储结构typedef struct LNode{ElemType data; //数据域struct LNode *next;//指针域}LNode, *LinkList;// typedef struct LNode *LinkList;// 另一种定义LinkList的方法// 构造一个空的线性表Lint InitList(LinkList *L){/*产生头结点L,并使L指向此头结点,头节点的数据域为空,不放数据的。
void *malloc(size_t)这里对返回值进行强制类型转换了,返回值是指向空类型的指针类型.*/(*L)= (LinkList)malloc(sizeof(struct LNode) );if( !(*L))exit(0);// 存储分配失败(*L)-〉next = NULL;// 指针域为空return 1;}// 销毁线性表L,将包括头结点在内的所有元素释放其存储空间。
int DestroyList(LinkList *L){LinkList q;// 由于单链表的每一个元素是单独分配的,所以要一个一个的进行释放while(*L ){q = (*L)—〉next;free(*L );//释放*L = q;}return 1;}/*将L重置为空表,即将链表中除头结点外的所有元素释放其存储空间,但是将头结点指针域置空,这和销毁有区别哦。
不改变L,所以不需要用指针。
*/int ClearList( LinkList L ){LinkList p,q;p = L—〉next;// p指向第一个结点while( p ) // 没到表尾则继续循环{q = p—>next;free( p );//释放空间p = q;}L—>next = NULL; // 头结点指针域为空,链表成了一个空表return 1;}// 若L为空表(根据头结点L—〉next来判断,为空则是空表),则返回1,// 否则返回0.int ListEmpty(LinkList L){if(L—>next ) // 非空return 0;elsereturn 1;}// 返回L中数据元素个数。
实验二 单链表基本操作
实验二单链表基本操作一实验目的1.学会定义单链表的结点类型,实现对单链表的一些基本操作和具体的函数定义,了解并掌握单链表的类定义以及成员函数的定义与调用。
2.掌握单链表基本操作及两个有序表归并、单链表逆置等操作的实现。
二实验要求1.预习C语言中结构体的定义与基本操作方法。
2.对单链表的每个基本操作用单独的函数实现。
3.编写完整程序完成下面的实验内容并上机运行。
4.整理并上交实验报告。
三实验内容1.编写程序完成单链表的下列基本操作:(1)初始化单链表La。
(2)在La中第i个元素之前插入一个新结点。
(3)删除La中的第i个元素结点。
(4)在La中查找某结点并返回其位置。
(5)打印输出La中的结点元素值。
2 .构造两个带有表头结点的有序单链表La、Lb,编写程序实现将La、Lb合并成一个有序单链表Lc。
合并思想是:程序需要3个指针:pa、pb、pc,其中pa,pb分别指向La表与Lb表中当前待比较插入的结点,pc 指向Lc表中当前最后一个结点。
依次扫描La和Lb中的元素,比较当前元素的值,将较小者链接到*pc 之后,如此重复直到La或Lb结束为止,再将另一个链表余下的内容链接到pc所指的结点之后。
3.构造一个单链表L,其头结点指针为head,编写程序实现将L逆置。
(即最后一个结点变成第一个结点,原来倒数第二个结点变成第二个结点,如此等等。
)四思考与提高1.如果上面实验内容2中合并的表内不允许有重复的数据该如何操作?2.如何将一个带头结点的单链表La分解成两个同样结构的单链表Lb,Lc,使得Lb中只含La表中奇数结点,Lc中含有La表的偶数结点?1.编写程序完成单链表的下列基本操作:(1)初始化单链表La。
(2)在La中第i个元素之前插入一个新结点。
(3)删除La中的第i个元素结点。
(4)在La中查找某结点并返回其位置。
(5)打印输出La中的结点元素值。
#include<stdio.h>#include<stdlib.h>#include <malloc.h>#define OK 1#define ERROR 0typedef int Status;typedef int ElemType;//定义存储结构typedef struct Lnode{int data; /*每个元素数据信息*/struct Lnode *next; /*存放后继元素的地址*/} LNode,*LinkList;int main(){void Create_L(LinkList &L,int n);void Print_L(LinkList L);Status ListInsert_L(LinkList &L,int i,ElemType e);Status ListDelete_L(LinkList &L,int i,ElemType &e);Status Find_L(LinkList L,int e);LinkList La;//创建单链表Laint n;printf("请输入链表La中的元素个数:\n");scanf("%d",&n);Create_L(La,n);//初始化单链表printf("现在La中的元素为:\n");Print_L(La);printf("-------------------------------------\n\n");printf("现在准备插入元素,请输入插入位置及所插入元素的值\n");int i,e;scanf("%d %d",&i,&e);ListInsert_L(La,i,e);printf("插入后La中的元素为:\n");Print_L(La);printf("-------------------------------------\n\n");printf("现在准备删除元素,请输入删除位置\n");scanf("%d",&i);ListDelete_L(La,i,e);printf("删除后La中的元素为:\n");Print_L(La);printf("-------------------------------------\n\n");printf("请输入所要查找元素的值:\n");scanf("%d",&e);Find_L(La,e);printf("所要查找元素的位置为:%d\n",Find_L(La,e)); }void Create_L(LinkList &L,int n){int j=1;L=(LinkList)malloc(sizeof(Lnode));L->next =NULL;//先建立一个带头结点的单链线性表L for(int i=n;i>0;--i){LinkList p=(LinkList)malloc(sizeof(Lnode));printf("请输入链表La中的第%d个元素:\n",j++);scanf("%d",&p->data);p->next=L->next;L->next =p;}//(逆序实现)/*LinkList q=L;for(int i=1;i<=n;i++){LinkList p=(LinkList)malloc (sizeof(Lnode));q->next=p;p->next=NULL;q=q->next ;printf("请输入链表La中的第%d个元素:\n",i);scanf("%d",&p->data);}//(正序实现)*/}//初始化单链表//输出单链表void Print_L(LinkList L){LinkList p;p=L->next;while(p){printf("%d ",p->data );p=p->next;}printf("\n");}//在单链表L的第i个位置前插入元素eStatus ListInsert_L(LinkList &L,int i,ElemType e) {LinkList p=L;int j=0;while(p&&j<i-1){p=p->next; ++j;}if(!p||j>i-1) return ERROR;LinkList s=(LinkList)malloc(sizeof(LNode));s->data=e; s->next=p->next;p->next=s;return OK;} //ListInsert_L//删除单链表L中第i个位置上的元素Status ListDelete_L(LinkList &L,int i,ElemType &e) {LinkList p=L;int j=0;while( p->next && j<i-1){p=p->next; ++j;}if(!p->next||j>i-1) return ERROR;LinkList q=p->next; p->next=q->next;e=q->data;free(q);return OK;}//LinkDelete_L/*查找元素并返回位置*/Status Find_L(LinkList L,int e){LinkList p=L->next;int j=1;while(p->data!=e&&p->next){p=p->next;j++;}if(p->data==e) return j;else{printf("无当前元素\n");return ERROR;}if(!p){printf("无当前元素\n");return ERROR;}}//定位2 .构造两个带有表头结点的有序单链表La、Lb,编写程序实现将La、Lb合并成一个有序单链表Lc。
建立非循环单链表的过程
建立非循环单链表的过程因为链表是离散存储的,每一个结点之间通过指针来链接。
所以要想创建一个非循环单链表,应该是先确定一个头结点(里面不存放任何有效数据),再确定一个尾结点(指针域为空,表明链表结束),然后在中间不断的用循环语句开辟一个个的新结点(用malloc 函数实现)。
如下图:我们先假定每一个结点的类型是:Struct Node{Int data;Struct Node *pNext;};为简单起见,我们规定结点中只存储整型数据。
现在让我们开始。
第一步:建立头结点和尾结点因为链表创建的过程是不断的在头结点和尾结点之间插入新的结点。
如果只有一个头结点的话,操作起来很不方便。
先定义两个指针变量:然后用malloc 函数开辟一个结点。
因为此时链表中只有一个结点,所以这个结点当然是头结点。
现在头结点有了,并且头指针指向了它,还需不需要另外创建一个尾结点呢?不需要。
为什么呢?我们只要让头指针和尾指针同时指向这个结点就可以了。
也就是说,在链表中只有一个结点的情况时,这个结点既可以看作是头结点,同时也可以看作是尾结点。
当然,因为尾结点最后没有结点了,所以我们还要让尾结点的指针域为空。
好,头结点和尾结点都有了,并且都有一个指针变量指向了它们。
那么现在就要开始创建新的结点了。
如何创建?当然要用循环。
用for 循环或者while 循环都可以。
喜欢哪样用哪样。
我们就用for 循环吧。
要用循环,首先要解决两个问题。
1、我要创建几个结点2、每个结点的值如何存储这些都好解决,无非是定义变量。
头结点尾结点·····新结点1新结点2新结点n下面开始循环:当然,这段代码还不够。
最重要的功能还没有。
我们还需要用malloc 函数动态开辟结点,并且让新开辟的结点和头结点与尾结点链接起来。
下面把代码补充完整。
下面用图来解释一下这段代码:简单起见,我们假定num=2,那for 循环就要循环两次。
c语言单链表程序代码
c语言单链表程序代码C语言单链表程序代码单链表是一种常见的数据结构,它由多个节点组成,每个节点包含一个数据域和一个指向下一个节点的指针。
以下是C语言实现单链表的程序代码:1. 定义节点结构体首先需要定义一个节点结构体,用来存储每个节点的数据和指针信息。
```typedef struct node {int data; // 数据域struct node *next; // 指向下一个节点的指针} Node;```2. 创建链表头节点创建一个头节点,它不存储任何数据,只是作为链表的起始点。
```Node *head = NULL;head = (Node*)malloc(sizeof(Node));head->next = NULL;```3. 插入新节点插入新节点时需要先创建一个新的节点,并将其插入到链表中合适的位置。
```Node *new_node = NULL;new_node = (Node*)malloc(sizeof(Node));new_node->data = new_data;// 找到插入位置Node *current = head;while (current->next != NULL && current->next->data < new_data) {current = current->next;}// 插入新节点new_node->next = current->next;current->next = new_node;```4. 删除指定数据的节点删除指定数据的节点时需要先找到该节点,并将其从链表中删除。
```// 找到要删除的节点Node *current = head;while (current->next != NULL && current->next->data != data) {current = current->next;}// 删除节点if (current->next != NULL) {Node *del_node = current->next;current->next = del_node->next;free(del_node);```5. 遍历链表遍历链表时需要从头节点开始,依次访问每个节点的数据。
数据结构c语言版上机报告单链表
数据结构C语言版上机报告:单链表序在数据结构课程中,单链表是一个重要的概念,也是C语言中常用的数据结构之一。
本次报告将深入探讨单链表的基本概念、操作方法以及应用场景,帮助读者更深入地理解和掌握这一数据结构。
一、概述1.1 单链表的定义单链表是一种线性表,它由一系列节点组成,每个节点包含两部分:数据域和指针域。
数据域用于存储数据元素,指针域用于指向下一个节点,通过指针将这些节点串联在一起,形成一个链表结构。
1.2 单链表的特点单链表具有以下特点:(1)动态性:单链表的长度可以动态地增加或减少,不需要预先分配固定大小的空间。
(2)插入和删除操作高效:在单链表中进行插入和删除操作时,只需要修改指针的指向,时间复杂度为O(1)。
(3)随机访问效率低:由于单链表采用链式存储结构,无法通过下标直接访问元素,需要从头节点开始依次遍历,时间复杂度为O(n)。
1.3 单链表的基本操作单链表的基本操作包括:创建、插入、删除、查找等。
这些操作是使用单链表时常常会涉及到的,下面将逐一介绍这些操作的具体实现方法和应用场景。
二、创建2.1 头插法和尾插法在C语言中,可以通过头插法和尾插法来创建单链表。
头插法是将新节点插入到链表的头部,尾插法是将新节点插入到链表的尾部,这两种方法各有优缺点,可以根据具体应用场景来选择。
2.2 应用场景头插法适合于链表的逆序建立,尾插法适合于链表的顺序建立。
三、插入3.1 在指定位置插入节点在单链表中,插入节点需要考虑两种情况:在链表头部插入和在链表中间插入。
通过对指针的操作,可以实现在指定位置插入节点的功能。
3.2 应用场景在实际应用中,经常会有需要在指定位置插入节点的情况,比如排序操作、合并两个有序链表等。
四、删除4.1 删除指定节点在单链表中,删除节点同样需要考虑两种情况:删除头节点和删除中间节点。
通过对指针的操作,可以实现删除指定节点的功能。
4.2 应用场景在实际应用中,经常会有需要删除指定节点的情况,比如删除链表中特定数值的节点等。
c语言链表定义
c语言链表定义链表是一种非常基础的数据结构,它的定义可以用多种编程语言来实现,其中最为常见的就是C语言。
本文将着重介绍C语言的链表定义。
第一步:首先,我们需要定义一个链表节点的结构体,用来存储链表中每个节点的数据信息以及指向下一个节点的指针。
具体代码如下所示:```struct ListNode {int val;struct ListNode *next;};```在这个结构体中,我们定义了两个成员变量,一个是表示节点值的val,一个是表示指向下一个节点的指针next。
其中,节点值可以是任意类型的数据,而指针next则是一个指向结构体类型的指针。
第二步:我们需要定义链表的头节点,通常会将头节点的指针定义为一个全局变量,方便在程序的不同部分中都能够访问。
这个头节点的作用是指向链表的第一个节点,同时也充当了哨兵节点的作用,使得链表的操作更加方便。
具体代码如下所示:```struct ListNode *list_head = NULL;```在这个全局变量中,我们定义了一个指向链表头节点的指针list_head,并将它初始化为NULL,表示目前链表为空。
第三步:链表的基本操作主要包括创建、插入、删除和遍历等。
我们将逐一介绍它们的定义方法。
1. 创建链表创建链表时,我们需要动态地分配内存,以保证每个节点的空间都是连续的而不会被覆盖。
具体代码如下所示:```struct ListNode *create_list(int arr[], int n) {struct ListNode *head = NULL, *tail = NULL;for (int i = 0; i < n; i++) {struct ListNode *node = (struct ListNode*)malloc(sizeof(struct ListNode));node->val = arr[i];node->next = NULL;if (head == NULL) {head = node;tail = node;} else {tail->next = node;tail = node;}}return head;}```在这个代码中,我们首先定义了链表的头节点head和尾节点tail,并将它们初始化为空。
循环单链表定义初始化及创建(C语言)
循环单链表定义初始化及创建(C语⾔)#include <stdio.h>#include <stdlib.h>/*** 含头节点循环单链表定义,初始化及创建*/#define OK 1;#define ERROR 0;//函数返回类型,表⽰函数运⾏结果的状态typedef int Status;//定义数据元素类型typedef char ElemType;//循环单链表定义typedef struct LoopLnode {ElemType data; //数据域,这⾥是char类型变量struct LoopLnode *next; //指针域,结构体类型指针} LoopLnode, *LoopLinkList;//循环单链表初始化Status InitList(LoopLinkList *list) {(*list)=(LoopLinkList)malloc(sizeof(LoopLnode));(*list)->next=(*list);(*list)->data='T'; //测试⽤,可不写return OK;}//1."头插法"创建仅含"头指针"的单向循环链表Status CreateList_H(LoopLinkList *list,ElemType arrData[],int length){int j;for(j=length-1;j>=0;j--){//新建结点LoopLnode *node;node=(LoopLnode*)malloc(sizeof(LoopLnode));node->data=arrData[j];node->next=NULL;//插⼊循环链表node->next=(*list)->next;(*list)->next=node; //list始终指向头结点}return OK;}//2."尾插法"创建仅含"头指针"的单向循环链表Status CreateList_R(LoopLinkList *list,ElemType arrData[],int length){LoopLnode *r;r=*list;int j;for(j=0;j<length;j++) {//新建结点LoopLnode *node;node=(LoopLnode*)malloc(sizeof(LoopLnode));node->data=arrData[j];node->next=NULL;//插⼊循环链表node->next=r->next;r=node;}return OK;}//3."头插法"创建仅含"尾指针"的单向循环链表Status BuildList_H(LoopLinkList *list,ElemType arrData[],int length){int j;for(j=length-1;j>=0;j--){//新建结点LoopLnode *node;node=(LoopLnode*)malloc(sizeof(LoopLnode));node->data=arrData[j];node->next=NULL;//node插⼊1号结点,list为尾指针node->next=(*list)->next->next; //node->next=头结点->nextif((*list)->next==(*list)) (*list)=node; //当只有头结点时(插⼊第⼀个结点时,⼿动设置node为尾指针)(*list)->next->next=node; //头结点->next=node;}return OK;}//4."尾插法"创建仅含"尾指针"的单向循环链表Status BuildList_R(LoopLinkList *list,ElemType arrData[],int length) {int j;for(j=0;j<length;j++) {//新建结点LoopLnode *node;node=(LoopLnode*)malloc(sizeof(LoopLnode));node->data=arrData[j];node->next=NULL;node->next=(*list)->next; //node->next=头结点(*list) = node; //尾指针 —> node}return OK;}int main(void){//产⽣待插⼊到链表的数据ElemType data1='A',data2='B',data3='C';ElemType waitInserted[]={data1,data2,data3,};//获得数组长度int arrLength=sizeof(waitInserted)/sizeof(waitInserted[0]);/**1.头插法建⽴只含头指针循环单链表**///定义链表并初始化LoopLinkList list1;InitList(&list1);//按既定数据建⽴链表CreateList_H(&list1,waitInserted,arrLength);//测试printf("%c\n",list1->next->next->next->next->next->next->data); //B/**2.尾插法建⽴只含头指针循环单链表**///定义链表并初始化LoopLinkList list2;InitList(&list2);//按既定数据建⽴链表CreateList_R(&list2,waitInserted,arrLength);//测试printf("%c\n",list1->next->next->next->next->next->next->data); //B/**3.头插法建⽴只含尾指针循环单链表**///定义链表并初始化LoopLinkList list3;InitList(&list3);//按既定数据建⽴链表BuildList_H(&list3,waitInserted,arrLength); //list3指向表尾//测试printf("%c\n",list3->next->next->next->next->next->next->next->next->next->data); //T/**4.尾插法建⽴只含尾指针循环单链表**///定义链表并初始化LoopLinkList list4;InitList(&list4);//按既定数据建⽴链表BuildList_H(&list4,waitInserted,arrLength); //list4指向表尾//测试printf("%c\n",list4->next->next->next->next->next->next->next->next->next->next->data); //A printf("\nEND!");return0;}。
C语言链表详解PPT课件
26
链表中结点删除
需要由两个临时指针: P1: 判断指向的结点是不是要删除的结点 (用于寻找); P2: 始终指向P1的前面一个结点;
27
图 11.19
4
结点里的指针是存放下一个结点的地址
Head
1249
1249
A 1356
1356
B 1475
1475
C 1021
1021
D Null
1、链表中的元素称为“结点”,每个结点包括两 个域:数据域和指针域;
2、单向链表通常由一个头指针(head),用于指 向链表头;
3、单向链表有一个尾结点,该结点的指针部分指
7
(4)删除操作是指,删除结点ki,使线性表的长度 减1,且ki-1、ki和ki+1之间的逻辑关系发生如下变 化:
删除前,ki是ki+1的前驱、ki-1的后继;删除后,ki-1 成为ki+1的前驱,ki+1成为ki-1的后继.
(5)打印输出
8
一个指针类型的成员既可指向其它类型的结构体数 据,也可以指向自己所在的结构体类型的数据
(x7,y7)
为了表示这种既有数据又有指针的情况, 引入结构这种数据类型。
3
11.7 用指针处理链表
链表是程序设计中一种重要的动态数据结构, 它是动态地进行存储分配的一种结构。
动态性体现为: 链表中的元素个数可以根据需要增加和减少,不 像数组,在声明之后就固定不变;
元素的位置可以变化,即可以从某个位置删除, 然后再插入到一个新的地方;
c语言单链表代码
c语言单链表代码单链表是一种数据结构,它由一系列节点构成,每个节点都包含一个数据域和一个指向下一个节点的指针域。
在C语言中,实现单链表需要使用指针和动态内存分配。
下面分步骤阐述一下如何实现单链表的代码。
1.定义单链表节点结构体单链表的节点包含两个域,一个是数据域用于存储数据,另一个是指针域用于指向下一个节点。
定义单链表节点结构体如下:```cstruct Node {int data;struct Node* next;};```其中,data表示节点存储的数据,next表示指向下一个节点的指针。
2.创建单链表创建单链表需要考虑两个问题,一个是如何在内存中分配节点的空间,另一个是如何将各个节点连接起来。
在C语言中使用malloc函数动态分配内存。
具体步骤如下:```cstruct Node *create_list(int n) {int i;struct Node *head = NULL;//定义头节点指针,初始化为空struct Node *p, *tail;//定义节点指针p和tail,用于遍历和尾插//读入n个节点的数据for (i = 0; i < n; i++) {p = (struct Node*)malloc(sizeof(struct Node));//动态分配内存scanf("%d", &p->data);p->next = NULL;//新节点的指针要初始化为空if (head == NULL)head = p;elsetail->next = p;//将上一个节点的next指向当前节点 tail = p;//更新尾节点指针}return head;//返回头节点指针}```其中,head指向链表的第一个节点,p表示当前节点,tail表示尾节点,next指向下一个节点。
3.遍历单链表遍历单链表需要用指针从头节点开始往下遍历。
单链表逆置
单链表逆置题目:创建一个单链表并且逆置单链表完成日期:2014-09-17一、需求分析1、有一个单链表的第一个结点指针为head,编写一个函数将该单链表逆置,即最后一个结点变成第一个结点,原来倒数第二个结点变成第二个结点。
在逆置中不能建立新的单链表.2、程序执行的命令包括:(1)创建第一个单链表;(2)逆位序输入n个元素的值,建立带表头节点的单链线性表L;(3)逆置链表设置头结点由指向第一个结点改成指向最后一个结点;(4)输出销毁。
3、测试数据输入:10 9 8 7 6 5 4 3 2 1二、概要设计1、链表的抽象数据类型定义为:typedef struct LNode{int data;struct LNode* next;}LNode, *LinkList;/* 创建一个链表*/void CreateList_1(LinkList *L, int n){/*逆位序输入n个元素的值,建立带表头节点的单链线性表L*/int i;LNode* p = NULL;*L = (LinkList)malloc(sizeof(LNode));(*L)->next = NULL; /*先建立一个带头结点的单链表*/for (i = n; i > 0; --i){p = (LinkList)malloc(sizeof(LNode)); /*生成新结点*/scanf("%d", &(p->data));p->next = (*L)->next;(*L)->next = p;}}2、本程序包含五个模块:(1)主程序模块:void main(){定义头结点;创建一个链表;输出;逆置;输出;销毁;}(2)逆位序输入n个元素的值,建立带表头节点的单链线性表L(3)先建立一个带头结点的单链表在生成新结点;(4)输出链表数据,逆置链表,设置头结点由指向第一个结点改成指向最后一个结点;(5)把结点1的指针域设置为NULL,最后返回L。
c语言多线程操作单链表
在C语言中,多线程操作单链表需要特别小心,因为这涉及到并发访问和修改共享数据的问题。
如果不正确地处理,可能会导致数据损坏或程序崩溃。
为了实现多线程操作单链表,可以使用以下方法:1. 锁机制:在访问链表之前,使用互斥锁(mutex)来保护链表,确保同一时间只有一个线程可以访问链表。
当线程需要修改链表时,需要先获取锁,然后进行修改,最后释放锁。
这样可以确保链表操作的原子性和一致性。
2. 读写锁:对于读多写少的场景,可以使用读写锁(read-write lock)。
读写锁允许多个线程同时读取链表,但只允许一个线程写入链表。
这样可以提高并发性能。
3. 条件变量:使用条件变量可以让线程等待链表发生变化。
当链表发生变化时,可以唤醒等待的线程。
这样可以避免线程频繁地检查链表是否发生变化,提高效率。
下面是一个简单的示例代码,演示了如何使用互斥锁实现多线程操作单链表:#include <stdio.h>#include <stdlib.h>#include <pthread.h>struct node {int data;struct node *next;};pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;struct node *head = NULL;void *add_node(void *arg) {pthread_mutex_lock(&mutex);struct node *new_node = (struct node *)malloc(sizeof(struct node));new_node->data = *((int *)arg);new_node->next = head;head = new_node;pthread_mutex_unlock(&mutex);return NULL;}void print_list() {pthread_mutex_lock(&mutex);struct node *p = head;while (p != NULL) {printf("%d ", p->data);p = p->next;}printf("\n");pthread_mutex_unlock(&mutex);}int main() {pthread_t tid1, tid2;int data1 = 1, data2 = 2;pthread_create(&tid1, NULL, add_node, &data1);pthread_create(&tid2, NULL, add_node, &data2);pthread_join(tid1, NULL);pthread_join(tid2, NULL);print_list(); // 输出:1 2return 0;}。
单链表的实现及其基本操作
单链表的实现及其基本操作结点的引⼊链表是⼀种链式存储结构,链式存储结构的特点是⽤⼀组任意的存储单元存储数据元素。
为了能正确表⽰数据元素之间的线性关系,需引⼊结点概念。
⼀个结点表⽰链表中的⼀个数据元素,节点中除了储存数据元素的信息,还必须存放指向下⼀个节点的的指针(单、双链表的最后⼀个节点除外,它们存储的是⼀个空指针NULL)结点的结构如下图所⽰:代码如下:1 typedef struct node{2int data;3struct node* pNext;4 }Node, *PNode;View Code注:这⾥假设结点中储存的是整型 (int) 的数据单链表由多个结点依次连接⽽成,我们不难想象出它结构:我们注意到:在第⼀个结点的前⾯多了⼀个头结点,这是为了处理空表的⽅便⽽引⼊的,它的指针指向链表的第⼀个结点,⽽它的data域不存放任何信息。
单链表的基本操作1.创建链表1 PNode createList()2 {3int len, value;45 PNode pHead = (PNode)(malloc(sizeof(Node)));6 PNode pTail = pHead;7 pTail->pNext = NULL;89 printf("请输⼊你要的节点个数:");10 scanf("%d", &len);11for(int i=1;i<=len;i++){12 printf("请输⼊第%d个节点的值:", i);13 scanf("%d", &value);1415 PNode pNew = (PNode)malloc(sizeof(Node));16 pNew->data = value;17 pTail->pNext = pNew;18 pTail = pNew;19 pTail->pNext = NULL;20 }2122return pHead;23 }View Code2.遍历链表void traverse(PNode pHead){printf("遍历结果为:\n");PNode pTra = pHead;while(pTra->pNext != NULL){printf("%d ", pTra->pNext->data);pTra = pTra->pNext;}printf("\n");}View Code3.判断链表是否为空1bool isEmpty(PNode pHead)2 {3if(pHead->pNext==NULL)4return true;5else6return false;7 }View Code4.链表长度1int length(PNode pHead)2 {3int len = 0;4while(pHead->pNext!=NULL){5 pHead = pHead->pNext;6 len++;7 }8return len;910 }View Code5.插⼊结点1bool insert(PNode pHead, int pos, int val)2 {3if(pos<1 || pos>length(pHead)){4return false;5 }else{6 PNode pInsert = pHead;7for(int i=1;i<pos;i++){8 pInsert = pInsert->pNext;9 }1011 PNode pNew = (PNode)malloc(sizeof(Node));12 pNew->data = val;13 pNew->pNext = pInsert->pNext;14 pInsert->pNext = pNew;1516return true;17 }1819 }View Code6.删除结点1bool del(PNode pHead, int pos)2 {3if(pos<1 || pos>length(pHead)){4return false;5 }else{6 PNode pDel = pHead;7for(int i=1;i<pos;i++){8 pDel = pDel->pNext;9 }1011if(pos==length(pHead)){12free(pDel->pNext);13 pDel->pNext = NULL;14 }else{15 PNode pNext = pDel->pNext->pNext;16free(pDel->pNext);17 pDel->pNext = pNext;18 }1920return true;2122 }232425 }View Code7.查找节点(1)按元素值查找1 PNode locate(PNode pHead, int value)2 {3 PNode p = pHead->pNext;4while(p&&p->data!=value){ //NULL 是 05 p = p->pNext;6 }7return p;8 }View Code(2)按序号查找1 PNode get(PNode pHead, int k)2 {3 PNode p = pHead;4for(int i=1;i<=k;i++){5 p = p->pNext;6 }7return p;89 }View Code完整代码1 #include<stdio.h>2 #include<stdlib.h>3 typedef struct node{4int data;5struct node* pNext;6 }Node, *PNode;78 PNode createList();9void traverse(PNode pHead);10bool isEmpty(PNode pHead);11int length(PNode pHead);12bool insert(PNode pHead, int pos, int val);13bool del(PNode pHead, int pos);14 PNode get(PNode pHead, int k); //按序号查找15 PNode locate(PNode pHead, int value);//按值查找 1617int main(void)18 {19//test2021return0;22 }2324 PNode createList()25 {26int len, value;2728 PNode pHead = (PNode)(malloc(sizeof(Node)));29 PNode pTail = pHead;30 pTail->pNext = NULL;3132 printf("请输⼊你要的节点个数:");33 scanf("%d", &len);34for(int i=1;i<=len;i++){35 printf("请输⼊第%d个节点的值:", i);36 scanf("%d", &value);3738 PNode pNew = (PNode)malloc(sizeof(Node));39 pNew->data = value;40 pTail->pNext = pNew;41 pTail = pNew;42 pTail->pNext = NULL;43 }4445return pHead;46 }474849void traverse(PNode pHead)50 {51 printf("遍历结果为:\n");52 PNode pTra = pHead;53while(pTra->pNext != NULL)54 {55 printf("%d ", pTra->pNext->data);56 pTra = pTra->pNext;57 }58 printf("\n");59 }6061bool isEmpty(PNode pHead)62 {63if(pHead->pNext==NULL)64return true;65else66return false;67 }6869int length(PNode pHead)70 {71int len = 0;72while(pHead->pNext!=NULL){73 pHead = pHead->pNext;74 len++;75 }76return len;7778 }7980bool insert(PNode pHead, int pos, int val)81 {82if(pos<1 || pos>length(pHead)){83return false;84 }else{85 PNode pInsert = pHead;86for(int i=1;i<pos;i++){87 pInsert = pInsert->pNext;88 }8990 PNode pNew = (PNode)malloc(sizeof(Node));91 pNew->data = val;92 pNew->pNext = pInsert->pNext;93 pInsert->pNext = pNew;9495return true;96 }9798 }99100bool del(PNode pHead, int pos)101 {102if(pos<1 || pos>length(pHead)){103return false;104 }else{105 PNode pDel = pHead;106for(int i=1;i<pos;i++){107 pDel = pDel->pNext;108 }109110if(pos==length(pHead)){111free(pDel->pNext);112 pDel->pNext = NULL;113 }else{114 PNode pNext = pDel->pNext->pNext;115free(pDel->pNext);116 pDel->pNext = pNext;117 }118119return true;120121 }122123124 }125126 PNode get(PNode pHead, int k)127 {128 PNode p = pHead;129for(int i=1;i<=k;i++){130 p = p->pNext;131 }132return p;133134 }135 PNode locate(PNode pHead, int value)136 {137 PNode p = pHead->pNext;138while(p&&p->data!=value){ //NULL 是 0 139 p = p->pNext;140 }141return p;142 }View Code。
单链表的类型定义与基本操作
• 基本思想
• 找到第i个结点 • 从单链表上摘除该结点(修改某些结点的指针域)
L
a1
… ai-1
× ai
ai+1
…
a NULL
n
L
a1
… ai-1
ai+1
…
a NULL
n
12
• 算法
void delete_lklist(lklist &l , int i)
{ lklist p,q;
p=find_lklist(l, i-1);
• C语言类型描述
typedef struct node{
datatype
data; /*数据元素类型*/
struct node *next; /*指针类型*/
} node, * lklist; /*结点类型*/
• node是结点类型 • lklist是指向node类型的指针
1
二、一些基本操作
1. 初始化 initiate_lklist(l)
else printf("不存在第i个结点");
}
13
}
return (j); }
3
3. 按序号查找 find_lklist(l, i) • 定义
• 查找单链表第i个元素,否则返回NULL
• 基本思想
• 从头指针出发,顺链域next逐个往下搜索,直到 找到第i个结点为止
4
• 算法
node *find_lklist(lklist l, int i)
{ lklist p=l;
e
ai
…
a1n0 NULL
• 算法
void insert_lklist(lklist &l , datatype x, int i)