c语言之链表编程

合集下载

c链表库函数

c链表库函数

c链表库函数全文共四篇示例,供读者参考第一篇示例:C语言是一种广泛应用于系统编程的高级语言,而链表(Linked List)是C语言中常用的数据结构之一。

在C语言中,链表并不像数组一样有现成的库函数可以直接调用,需要通过自定义函数来实现链表的操作。

为了方便使用链表,不少开发者封装了链表操作的库函数,提供了一些常用的链表操作接口,以供开发者使用。

本文将介绍一些常见的C链表库函数及其用法。

一、链表的概念及基本操作链表是一种线性表的存储结构,由若干节点(Node)组成,每个节点包含数据域和指针域。

数据域用于存放数据,指针域用于指向下一个节点。

链表的最后一个节点指针域为空(NULL),表示链表的末尾。

常见的链表操作包括创建链表、插入节点、删除节点、遍历链表、查找节点等。

下面我们来看看C语言中常用的链表库函数。

二、常见的C链表库函数1. 创建链表在C语言中,创建链表的函数通常包括初始化链表头节点和链表节点的操作。

```#include <stdio.h>#include <stdlib.h>//定义链表节点typedef struct node {int data;struct node* next;} Node;2. 插入节点插入节点是链表操作中的重要操作,可以在链表的任意位置插入新节点。

常见的插入方式包括头部插入和尾部插入。

```//头部插入节点void insertNodeAtHead(Node* head, int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->next = head->next;head->next = newNode;}以上是常见的C链表库函数,这些函数可以帮助我们更方便地操作链表。

在实际开发中,可以根据需要自定义更多的链表操作函数,以满足具体的需求。

《数据结构(C语言版)》严蔚敏代码实现———链表

《数据结构(C语言版)》严蔚敏代码实现———链表

《数据结构(C语⾔版)》严蔚敏代码实现———链表⼀、前⾔哈喽,⼤家好~我是熊⼦q,我⼜来了!他来了他来了,他带着代码过来了!今天要分享的代码是链表!快快搬着⼩板凳!⼆、代码严奶奶的书中预定义了⼀些预定义常量和类型,⼤家可以 新建⼀个y.h⽂件粘贴以下内容, 然后再去复制代码哦。

y.h⽂件内容:/*** 严奶奶书中的预定义常量和类型**///函数结果状态代码#define TRUE 1 //成功#define FALSE 0 //失败#define OK 1 //成功#define ERROR 0 //错误#define INFEASIBLE -1 //不可实⾏#define OVERFLOW -2 //溢出//Status 是函数的类型,其值是函数结果状态代码typedef int Status;链表LinkList.cpp:#include "y.h"#include <iostream>#include <cstdlib>#include <cstdio>using namespace std;typedef int ElemType;/*** 严奶奶单链表的实现* by 熊⼦q 2021.2.1**/typedef struct LNode{ElemType data;struct LNode *next;}LNode,*LinkList;//获取元素Status GetElem(LinkList L, int i, ElemType &e){//L为带头结点的单链表的头指针//当第i个元素存在时,其值赋给e并返回OK,否则返回ERRORLNode *p = L->next; //p指向第⼀个结点int j = 1; //j为计数器while(p && j<i){ //寻找第i个位置p = p->next;++j;}if(!p || j>i) return ERROR; //第i个元素不存在e = p->data; //否则获取第i个元素return OK;}//插⼊元素,时间复杂度O(n)Status Insert(LinkList &L, int i, ElemType e){//在带头结点的单链表L中第i个位置之前插⼊元素eLNode *p = L;int j = 0;while(p && j<i-1){p = p->next;++j;}if(!p || j>i-1) return ERROR; //i⼩于1或者⼤于表长加1LNode *q = (LNode*)malloc(sizeof(LNode));q->data = e; //插⼊数据q->next = p->next;p->next = q;return OK;}//删除元素,时间复杂度O(n)Status ListDelete(LinkList &L, int i, ElemType e){//在带头结点的单链表L中,删除第i个元素,并由e返回其值LNode *p = L->next;int j = 1;while(p && j<i-1){p = p->next;++j;} //寻找i的前驱元素if(!(p->next) || j>i-1) return ERROR; //删除位置不合理,i元素不存在或 LNode *q = p->next; //删除第i个位置元素,并释放该结点 p->next = q->next;e = q->data;free(q);return OK;}//创建链表void CreateList(LinkList &L, int n){//逆序输⼊n个元素的值,建⽴带头结点的单链表LL = (LinkList)malloc(sizeof(LNode));L->next = NULL; //建⽴⼀个头结点printf("请输⼊数据:\n");for(int i=n;i>0;--i){LNode *p = (LNode*)malloc(sizeof(LNode));scanf("%d",&(p->data));p->next = L->next; L->next = p;}}//合并两个有序链表void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc){//已知单链表La和Lb的元素按值⾮递减排列//归并La和Lb得到新的单链表Lc,Lc的元素也按值⾮递减排列LNode *pa = La->next;LNode *pb = Lb->next;LNode *pc = La; //⽤La的头结点作为Lc的头结点Lc = pc;while(pa && pb){//取⼆者中较⼤值添加到Lc中if(pa->data > pb->data){//先添加该节点为pc的后继元素,然后pc和pa指针都后移pc->next = pa; pc = pc->next; pa = pa->next;}else{pc->next = pb; pc = pc->next; pb = pb->next;}}pc->next = pa? pa: pb; //插⼊剩余段free(Lb); //释放Lb的头结点}//输出单链表void Display(LinkList &L){LNode *p = L->next;printf("单链表的内容为:");while(p){printf("%d",p->data);if(p->next) printf("->");else printf("\n");p = p->next;}}int main(){LinkList l;CreateList(l, 5);Display(l);// printf("在第%d位插⼊%d",1,123);// Insert(l, 1, 123);// Display(l);int tmp;GetElem(l, 2, tmp);printf("%d",tmp);return 0;}三、运⾏截图四、附录如果你想看其他的代码,下⾯有链接哦:。

c语言超时重发机制的链表

c语言超时重发机制的链表

c语言超时重发机制的链表C语言超时重发机制的链表引言:在网络通信中,超时重发机制是一种常见的应对网络延迟和丢包的技术手段。

本文将介绍如何使用C语言实现一个超时重发机制的链表,以及其原理和应用。

一、超时重发机制的链表超时重发机制的链表是一种数据结构,用于管理需要进行超时重发的数据包。

它的主要特点是可以按照发送顺序进行管理,并且能够自动检测超时并进行重发操作。

二、链表的基本结构链表是由一系列节点组成的数据结构,每个节点包含一个数据域和一个指针域。

在超时重发机制的链表中,每个节点代表一个数据包,并且需要额外包含超时时间和重发次数等信息。

三、链表的初始化在使用链表之前,需要进行初始化操作。

初始化操作主要包括创建链表头节点,并将头节点的指针域置空。

四、数据包的插入在发送数据包时,将数据包插入到链表的末尾。

这需要遍历链表,找到最后一个节点,并将其指针域指向新节点。

五、超时检测与重发超时检测是链表中的重要操作,用于判断是否有数据包超时。

当一个数据包超时时,需要将其重新发送,并更新超时时间和重发次数等信息。

六、数据包的删除当一个数据包发送成功后,需要从链表中删除。

删除操作需要遍历链表,找到对应的节点,并更新前后节点的指针域。

七、链表的销毁当所有数据包都发送完成或不再需要重发时,需要销毁链表。

销毁链表操作主要包括释放所有节点的内存空间,并将链表头节点的指针域置空。

八、超时重发机制的应用超时重发机制在网络通信中广泛应用于保证数据可靠性和提高传输效率。

例如,在TCP协议中,超时重发机制被用于保证数据包的可靠传输。

九、注意事项在实现超时重发机制的链表时,需要注意以下事项:1. 设置合理的超时时间,以适应不同的网络环境。

2. 避免重复发送已经成功发送的数据包,以节省网络带宽和资源。

3. 考虑异常情况,如网络中断或故障,需要对链表进行适当的处理。

结论:超时重发机制的链表是一种实现超时重发的重要数据结构。

它可以有效地应对网络延迟和丢包等问题,提高数据传输的可靠性和效率。

[转载整理]C语言链表实例

[转载整理]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语言二路归并链表二路归并链表是一种常见的链表操作,它主要用于将两个有序链表合并成一个新的有序链表。

在这篇文章中,我们将通过一个实际的例子来解释二路归并链表的思想和实现方法。

假设我们有两个有序链表,分别是链表A和链表B。

我们的目标是将这两个链表合并成一个新的有序链表。

要实现这个目标,我们可以使用递归或迭代的方法。

我们来看一下递归的方法。

递归的思想是将原问题拆分为多个子问题,然后通过解决子问题来解决原问题。

在二路归并链表中,我们可以将链表A的头节点与链表B的头节点进行比较,较小的节点作为新链表的头节点。

然后,我们将较小节点的下一个节点与另一个链表的头节点进行比较,重复这个过程,直到其中一个链表为空。

最后,我们将非空链表的剩余部分直接连接到新链表的末尾。

接下来,我们来看一下迭代的方法。

迭代的思想是通过循环来解决问题。

在二路归并链表中,我们可以使用两个指针分别指向链表A 和链表B的头节点。

然后,我们比较两个指针指向的节点的值,较小的节点作为新链表的节点,并将指针向后移动一位。

重复这个过程,直到其中一个链表为空。

最后,我们将非空链表的剩余部分直接连接到新链表的末尾。

无论是递归还是迭代的方法,二路归并链表的时间复杂度都是O(n+m),其中n和m分别是链表A和链表B的长度。

这是因为我们需要遍历链表A和链表B的所有节点,并将它们连接到新链表中。

通过以上的描述,我们可以看出,二路归并链表是一种非常实用的链表操作,它可以帮助我们将两个有序链表合并成一个新的有序链表。

无论是递归还是迭代的方法,都可以有效地实现这个目标。

希望通过这篇文章的介绍,读者能够更好地理解和掌握二路归并链表的思想和实现方法。

链表c语言经典例题

链表c语言经典例题

链表c语言经典例题
链表是计算机科学中的经典数据结构之一,常用于存储和操作动态数据。

以下是一些常见的链表例题,可以帮助理解链表的基本操作和应用。

1. 链表的创建:
- 创建一个空链表。

- 创建一个包含指定节点值的链表。

2. 链表的插入操作:
- 在链表的头部插入一个节点。

- 在链表的尾部插入一个节点。

- 在指定位置插入一个节点。

3. 链表的删除操作:
- 删除链表的头节点。

- 删除链表的尾节点。

- 删除指定数值的节点。

4. 链表的查找操作:
- 查找链表中指定数值的节点。

- 查找链表的中间节点。

5. 链表的逆序操作:
- 反转整个链表。

- 反转链表的前 N 个节点。

- 反转链表的一部分区间内的节点。

6. 链表的合并操作:
- 合并两个有序链表,使其有序。

- 合并 K 个有序链表,使其有序。

7. 链表的环检测:
- 判断链表中是否存在环,若存在,则返回环的起始节点。

8. 链表的拆分操作:
- 将一个链表按照奇偶位置拆分成两个链表。

以上是一些链表的经典例题,通过解答这些例题,可以加深对链表结构和基本操作的理解。

在编写对应的 C 语言代码时,需要注意链表节点的定义、指针的使用以及内存的动态分配和释放等问题。

c语言链表结点数据之和

c语言链表结点数据之和

c语言链表结点数据之和(原创实用版)目录1.链表结点的概念和结构2.链表结点数据的计算方法3.C 语言中链表结点数据的和的计算方法正文链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个指向下一个节点的指针。

链表结点是链表中的基本单元,它包含一个数据元素和一个指向下一个结点的指针。

链表结点数据的计算方法是比较简单的。

对于一个单链表,我们可以使用遍历法来计算链表结点数据的和。

具体来说,我们从链表的头结点开始,依次遍历链表中的每个结点,将当前结点的数据元素累加到一个变量中。

当遍历完链表后,该变量中存储的就是链表结点数据的和。

在 C 语言中,我们可以使用循环和指针来实现链表结点数据的和的计算方法。

假设我们有一个链表,其头结点为 head,我们需要计算链表结点数据的和,可以使用以下代码实现:```cint sum = 0; // 定义一个变量用于存储链表结点数据的和ode *p = head; // 定义一个指针 p 指向链表的头结点// 使用循环遍历链表,计算链表结点数据的和while (p!= NULL) {sum += p->data; // 将当前结点的数据元素累加到变量 sum 中 p = p->next; // 将指针 p 指向下一个结点}// 输出链表结点数据的和printf("链表结点数据的和为:%d", sum);```上述代码中,我们定义了一个指针变量 p,使其指向链表的头结点。

然后使用 while 循环遍历链表,每次循环将当前结点的数据元素累加到变量 sum 中,并将指针 p 指向下一个结点。

当指针 p 指向 NULL 时,说明遍历完整个链表,此时变量 sum 中存储的就是链表结点数据的和。

最后,我们使用 printf 语句输出链表结点数据的和。

十字链表(C语言版本)

十字链表(C语言版本)

⼗字链表(C语⾔版本)内容其实跟以前写的⼀样的,改⼀个C语⾔版本。

#include <stdio.h>#include <stdlib.h>#include <math.h>typedef struct DoubleNode {int roleId;int x;int y;struct DoubleNode* xPrev;struct DoubleNode* xNext;struct DoubleNode* yPrev;struct DoubleNode* yNext;} DoubleNode;typedef struct Scene {DoubleNode* _head;DoubleNode* _tail;} Scene;void _add_node(struct Scene* scene, DoubleNode* node);void _leave_scene(DoubleNode* node);// 初始化场景struct Scene* new_scene();// 进⼊场景DoubleNode* enter_scene(struct Scene* scene, int roleId, int x, int y);// 离开场景void leave_scene(DoubleNode* node);// 场景内移动void role_move(struct Scene* scene, DoubleNode* node, int x, int y);// 获取AOIvoid get_aoi(struct Scene* scene, DoubleNode* node, int xAreaLen, int yAreaLen);// --------------------------------------------------struct Scene* new_scene() {struct Scene* scene = (struct Scene*)malloc(sizeof(struct Scene));DoubleNode* _head = (struct DoubleNode*)malloc(sizeof(struct DoubleNode));DoubleNode* _tail = (struct DoubleNode*)malloc(sizeof(struct DoubleNode));_head->roleId = _head->x = _head->y = 0;_tail->roleId = _tail->x = _tail->y = 0;_head->xPrev = _tail->xNext = NULL;_head->yPrev = _tail->yNext = NULL;_head->xNext = _head->yNext = _tail;_tail->xPrev = _tail->yPrev = _head;scene->_head = _head;scene->_tail = _tail;return scene;}DoubleNode* enter_scene(struct Scene* scene, int roleId, int x, int y) {DoubleNode* node = (DoubleNode*)malloc(sizeof(DoubleNode));node->roleId = roleId;node->x = x;node->y = y;_add_node(scene, node);return node;}void _add_node(struct Scene* scene, DoubleNode* node) {DoubleNode* cur = scene->_head->xNext;while(cur != NULL){if((cur->x > node->x) || cur == scene->_tail) {node->xNext = cur;node->xPrev = cur->xPrev;cur->xPrev->xNext = node;cur->xPrev = node;break;}cur = cur->xNext;}cur = scene->_head->yNext;while(cur != NULL){if((cur->y > node->y) || cur == scene->_tail) {node->yNext = cur;node->yPrev = cur->yPrev;cur->yPrev->yNext = node;cur->yPrev = node;break;}cur = cur->yNext;}}void _leave_scene(DoubleNode* node) {node->xPrev->xNext = node->xNext;node->yPrev->yNext = node->yNext;node->xNext->xPrev = node->xPrev;node->yNext->yPrev = node->yPrev;node->xPrev = node->xNext = NULL;node->yPrev = node->yNext = NULL;}void leave_scene(DoubleNode* node) {_leave_scene(node);free(node);}void print_scene(struct Scene* scene) {DoubleNode* cur = scene->_head->xNext;while(cur != scene->_tail) {printf("%d(%d, %d)\n", cur->roleId, cur->x, cur->y);cur = cur->xNext;}printf("\n");cur = scene->_head->yNext;while(cur != scene->_tail) {printf("%d(%d, %d)\n", cur->roleId, cur->x, cur->y);cur = cur->yNext;}}void role_move(struct Scene* scene, DoubleNode* node, int x, int y) {_leave_scene(node);node->x = x;node->y = y;_add_node(scene, node);}void get_aoi(struct Scene* scene, DoubleNode* node, int xAreaLen, int yAreaLen) { DoubleNode* cur = node->xNext;while(cur != scene->_tail){if(cur->x < node->x + xAreaLen){if(abs(cur->y - node->y) < yAreaLen){printf("aoi = %d(%d, %d)\n", cur->roleId, cur->x, cur->y);}}else{break;}cur = cur->xNext;}cur = node->xPrev;while(cur != scene->_tail){if(node->x < cur->x + xAreaLen){if(abs(cur->y - node->y) < yAreaLen){printf("aoi = %d(%d, %d)\n", cur->roleId, cur->x, cur->y);}}else{break;}cur = cur->xPrev;}}void main() {struct Scene* scene = new_scene();printf("\n== enter_scene == \n");enter_scene(scene, 1001, 1, 5);enter_scene(scene, 1002, 6, 6);enter_scene(scene, 1003, 3, 1);enter_scene(scene, 1004, 2, 2);struct DoubleNode* node1 = enter_scene(scene, 1005, 5, 4); struct DoubleNode* node2 = enter_scene(scene, 1006, 3, 3); print_scene(scene);printf("\n== leave_scene == \n");leave_scene(node1);print_scene(scene);printf("\n== role_move == \n");role_move(scene, node2, 2, 2);print_scene(scene);printf("\n== get_aoi == \n");get_aoi(scene, node2, 2, 2);}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2.1 试描述头指针、头结点、开始结点的区别,并说明头指针和头结点的作用。

头指针:存放链表首地址的指针变量。

头结点:链表的开始结点之前的一个同类型结点。

开始结点:链表的第一个元素所在的结点。

头指针的作用:用于确定链表的地址。

头结点的作用:方便于处理开始结点的操作和处理其它结点的操作保持一致,也方便于处理空表的操作和处理非空表的操作保持一致。

2.2 有哪些链表可由一个尾指针来唯一确定?即从尾指针出发能访问链表上任何一个结点。

单循环链表,双链表,双循环链表2.3 设线性表存放在向量A[arrsize]的前elenum个分量中,且递增有序。

试写一算法,将x 插入到线性表的适当位置上,以保持线性表的有序性。

并且分析算法的时间复杂度。

#define arrsize 100int InsertOrder(int A[], int elenum, int x){ int i=elenum-1;if (elenum==arrsize) //在顺序表上进行插入操作必须先判满{ printf(“full”);return 0;}while (i>=0&&A[i]>x){ A[i+1]=A[i];i--;} //从后往前进行比较,比较的同时完成移动A[i+1]=x;elenum++;return elenum; //返回变化之后的表长} //本题也可以先进行比较,比较的结果就是找到了插入的合适位置,然后再完成插入操作。

但这样做比较耗时。

假设n=elenum,则时间复杂度:最坏O(n),最好O(1),平均O(n)2.4 用向量作存储结构,试设计一个算法,仅用一个辅助结点,实现将线性表中的结点循环右移k位的运算,并且分析算法的时间复杂度。

void MoveKList(int a[],int n,int k){ int i, j, temp;for (i=1; i<=k; i++) //外层for循环控制循环右移的次数i{ temp=a[n-1]; //把表尾元素保存到辅助结点变量temp中for (j=n-2; j>=0; j--)a[j+1]=a[j]; //内层for循环完成一次整体右移一位a[0]=temp; //把原来的表尾元素移至表头}}时间复杂度T(n) = k*n = O(n)2.5 已知带头结点的动态单链表L中的结点是按整数值递增排列的,试写一算法将值为x的结点插入表L中,使L仍然有序。

typedef int datatype;typedef struct node{ datatype data;struct node *next;} linklist; //linklist结构体类型描述void InsertListOrder(linklist *L, datetype x){ linklist *p=L; //对寻位指针p初始化linklist *s=(linklist *)malloc(sizeof(linklist)); //使用强制类型转换将新结点的地址赋给指针s s->data=x;while((p->next)&&(p->next->data<x))p=p->next; //后移寻位指针s->next=p->next;p->next=s;} //本题也可以采用两个寻位指针p和q,让q始终跟随p的后移而后移。

2.6 设计一算法,逆置带头结点的动态单链表L。

typedef int datatype;typedef struct node{ datatype data;struct node *next;} linklist;void Reverse(linklist *L){ linklist *p,*q;p=L->next;q=L->next;L->next=NULL;while(q){ q=q->next;p->next=L->next;L->next=p;p=q;}} //用指针q遍历结点,指针p跟随指针q,使用头插法把当前结点*p插入到修改之后的单链表中。

2.7 试编写在带头结点的动态单链表和静态单链表上实现线性表操作Length(L)的算法,并将长度写入头结点的数据域中。

(1) typedef int datatype;typedef struct node{ datatype data;struct node *next;} linklist;void Length1(linklist *L){ linklist *p=L-next;int i=0;while(p){ i++;p=p->next;}L->data=i; //按照题目要求,将表长写入头结点的数据域中。

}(2) #define maxsize 1024typedef int datatype;typedef struct{ datatype data;int next;} node;node nodepool[maxsize];void Length2(int L){ int i=0, p=nodepool[L].next;while(p){ i++;p=nodepool[p].next;}nodepool[L].data=i;}2.8 假设有两个按元素值递增有序排列的线性表A和B,均以单链表①作存储结构,试编写算法将A表和B表归并成一个按元素值递减有序(即非递增有序,允许值相同)排列的线性表C,并要求利用原表(即A表和B表)的结点空间存放表C。

①今后若不特别指明,链表均是指动态链表,且可以带头结点。

typedef int datatype;typedef struct node{ datatype data;struct node *next;} linklist;linklist *Connect ( linklist *A, linklist *B ){ linklist *C, *p, *q, *r;C=A; //C为最后返回的链表头指针p=A->next; //p总是指向链表A中当前正在比较的结点q=B->next; //q总是指向链表B中当前正在比较的结点C->next=NULL; //置空链表Cwhile(p&&q) //当链表A和链表B中还有没比较的结点时{ if (p->data<q->data){ r=p; p=p->next; }else{ r=q; q=q->next; } //r总是指向*p和*q二者中数据较小的结点r->next=C->next;C->next=r; //将*r按照头插法插入到链表C中if(!p) //如果链表A中所有结点都链接到链表C中后,链表B中还有结点,while(q) //将链表B中剩余的未比较过的结点全部按照头插法插入到链表C中{ r=q; q=q->next; r->next=C->next; C->next=r; }else //如果链表B中所有结点都链接到链表C中后,链表A中还有结点,while(p) //将链表A中剩余的未比较过的结点全部按照头插法插入到链表C中{ r=p; p=p->next; r->next=C->next; C->next=r; }free(B); //释放链表B的头结点return C;}2.9 假设在长度大于1的单循环链表中,既无头结点也无头指针。

s为指向链表中某个结点的指针,试编写算法删除结点*s的直接前趋结点。

typedef int datatype;typedef struct node{ datatype data;struct node *next;} linklist;void DeleteBefore ( linklist *s ){ linklist *p=s;while(p->next->next!=s)p=p->next;free(p->next);p->next=s;}2.10 已知,由单链表表示的线性表中,含有三类字符的数据元素(如:字母字符、数字字符和其它字符),试编写算法构造三个以循环链表表示的线性表,使每个表中只含同一类的字符,且利用原表中的结点空间作为这三个表的结点空间,头结点可另辟空间。

typedef char datatype;typedef struct node{datatype data;struct node *next;} linklist;//L为等待分解的单链表,最后得到的包含字母字符的链表的首地址作为该函数的返回值被返回,得到的包含数字字符的链表的首地址被参数*LB带回,得到的包含其它字符的链表的首地址被参数*LC带回。

linklist * Decompose ( linklist *L, linklist **LB, linklist **LC ){//A, B, C分别用于保存分解之后得到的三个循环链表的首地址//pa, pb, pc分别指向三个循环链表当前的尾结点//p总是指向原单链表L中当前正在判断类型,正在等待处理的结点linklist *A, *B, *C, *pa, *pb, *pc, *p;A=L;B=(linklist *)malloc(sizeof(linklist));C=(linklist *)malloc(sizeof(linklist));pa=A; pb=B; pc=C; p=A->next;while(p) //只要p不为空,就意味着原单链表L中仍然有未处理的结点{if(((’a’<=p->data)&&(p->data<=’z’))||((’A’<=p->data)&&(p->data<=’Z’))) {pa->next=p; pa=p; p=p->next;} //将*p链接到链表A的终端,然后p后移else if((’0’<=p->data)&&(p->data<=’9’)){pb->next=p; pb=p; p=p->next;} //将*p链接到链表B的终端,然后p后移else{pc->next=p; pc=p; p=p->next;} //将*p链接到链表C的终端,然后p后移}//让链表A、B、C都循环起来pa->next=A;pb->next=B;pc->next=C;*LB=B; //通过指针类型的变量LB带回循环链表B的首地址*LC=C; //通过指针类型的变量LC带回循环链表C的首地址return A; //通过函数返回值带回循环链表A的首地址}2.11 设有一个双链表,每个结点中除有prior、data和next三个域外,还有一个访问频度域freq,在链表被起用之前,其值均初始化为零。

相关文档
最新文档