单链表实例
数据结构与算法——单链表的实现及原理
数据结构与算法——单链表的实现及原理1. 单链表的原理 链表是线性表的链式存储⽅式,逻辑上相邻的数据在计算机内的存储位置不必须相邻,那么怎么表⽰逻辑上的相邻关系呢?可以给每个元素附加⼀个指针域,指向下⼀个元素的存储位置。
如图所⽰: 从图中可以看出,每个结点包含两个域:数据域和指针域,指针域存储下⼀个结点的地址,因此指针指向的类型也是结点类型链表的核⼼要素:Ø 每个节点由数据域和指针域组成 Ø 指针域指向下⼀个节点的内存地址。
1.1 结构体定义1 Typedef struct LinkNode2 {3 ElemType data; //节点中存放数据的类型4struct LinkNode* next; //节点中存放下⼀节点的指针5 }LinkList, LinkNode;2. 单链表初始化链表的节点均单向指向下⼀个节点,形成⼀条单向访问的数据链1//单链表的初始化2 typedef struct _LinkNode3 {4int data; //结点的数据域5struct _LinkNode* next; //结点的指针域6 }LinkNode, LinkList; //链表节点、链表78bool InitList(LinkList*& L) //构造⼀个空的单链表 L9 {10 L = new LinkNode; //⽣成新结点作为头结点,⽤头指针 L 指向头结点11if(!L)return false; //⽣成结点失败12 L->next=NULL; //头结点的指针域置空13return true;14 }3. 单链表增加元素 - 单链表前插法插⼊节点的要素就是要找到要插⼊位置的前⼀个节点,将这个节点的Next赋值给新节点,然后将新节点的地址赋值给前⼀个节点的Next便可,任意位置插⼊和前插法均是如此。
1//前插法2bool ListInsert_front(LinkList * &L, LinkNode * node) //参数1 链表指针参数2 要插⼊的节点元素3 {4if (!L || !node) return false; //如果列表或节点为空返回 false5 node->next = L->next; //将头节点指向节点1的地址赋值给要插⼊节点的指针域,使要插⼊的节点先与后部相连6 L->next = node; //将插⼊节点的地址赋值给头结点的指针域,使要插⼊节点与头结点相连78return true;9 }4. 单链表增加元素 - 单链表尾插法1//尾插法2bool ListInsert_back(LinkList*& L, LinkNode* node)3 {4 LinkNode* last = NULL; //创建空指针,5if (!L || !node) return false; //如果列表或节点为空返回 false67 last = L;8while (last->next) last = last->next; //使⽤ last 找到最后⼀个节点910 node->next = NULL; //要插⼊节点由于在尾部,指针域置为 NULL11 last->next = node; //将要插⼊节点的地址赋值给之前的尾部节点的指针域,将要插⼊节点放置到尾部12return true;13 }5. 单链表增加元素 - 单链表任意位置插⼊插⼊节点的要素就是要找到要插⼊位置的前⼀个节点,将这个节点的Next赋值给新节点,然后将新节点的地址赋值给前⼀个节点的Next便可,任意位置插⼊和前插法均是如此。
数据结构课程设计-单链表
目录1 选题背景 (1)2 方案与论证 (1)2。
1 链表的概念和作用 (1)2。
3 算法的设计思想 (2)2。
4 相关图例 (3)2.4.1 单链表的结点结构 (3)2.4。
2 算法流程图 (3)3 实验结果 (4)3.1 链表的建立 (4)3.2 单链表的插入 (4)3.3 单链表的输出 (5)3.4 查找元素 (5)3。
5 单链表的删除 (5)3。
6 显示链表中的元素个数(计数) (5)4 结果分析 (6)4。
1 单链表的结构 (6)4。
2 单链表的操作特点 (6)4。
2。
1 顺链操作技术 (6)4.2。
2 指针保留技术 (6)4。
3 链表处理中的相关技术 (6)5 设计体会及今后的改进意见 (6)参考文献 (8)附录代码: (8)1 选题背景陈火旺院士把计算机60多年的发展成就概括为五个“一”:开辟一个新时代-—--信息时代,形成一个新产业-—-—信息产业,产生一个新科学—---计算机科学与技术,开创一种新的科研方法-—--计算方法,开辟一种新文化---—计算机文化,这一概括深刻影响了计算机对社会发展所产生的广泛而深远的影响。
数据结构和算法是计算机求解问题过程的两大基石。
著名的计算机科学家P.Wegner指出,“在工业革命中其核心作用的是能量,而在计算机革命中其核心作用的是信息”.计算机科学就是“一种关于信息结构转换的科学”.信息结构(数据结构)是计算机科学研究的基本课题,数据结构又是算法研究的基础。
2 方案与论证2。
1 链表的概念和作用链表是一种链式存储结构,链表属于线性表,采用链式存储结构,也是常用的动态存储方法。
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
以“结点的序列”表示线性表称作线性链表(单链表)单链表是链式存取的结构,为找第 i 个数据元素,必须先找到第 i-1 个数据元素。
写一求单链表的结点数目listlength(l)的算法。
写一求单链表的结点数目listlength(l)的算法。
单链表是一种常见的数据结构,它由一系列结点组成,每个结点都有一个指向下一个结点的指针。
求单链表的结点数目listlength(l)是一个常见的问题,下面我们就来讨论一下如何求解这个问题。
首先,我们需要定义一个变量count,用来记录单链表的结点数目。
然后,我们从单链表的头结点开始遍历,每遍历一个结点,count就加1,直到遍历到最后一个结点,count的值就是单链表的结点数目。
具体的算法步骤如下:
(1)定义一个变量count,用来记录单链表的结点数目,初始值为0。
(2)从单链表的头结点开始遍历,每遍历一个结点,count就加1。
(3)直到遍历到最后一个结点,count的值就是单链表的结点数目。
(4)返回count的值。
上述就是求单链表的结点数目listlength(l)的算法,它的时间复杂度为O(n),空间复杂度为O(1),其中n为单链表的结点数目。
总之,求单链表的结点数目listlength(l)是一个常见的问题,上述算法可以有效地解决这个问题,它的时间复杂度和空间复杂度都很低,是一种非常有效的算法。
数据结构-单链表基本操作实现(含全部代码)
数据结构-单链表基本操作实现(含全部代码)今天是单链表的实现,主要实现函数如下:InitList(LinkList &L) 参数:单链表L 功能:初始化时间复杂度 O(1)ListLength(LinkList L) 参数:单链表L 功能:获得单链表长度时间复杂度O(n)ListInsert(LinkList &L,int i,ElemType e) 参数:单链表L,位置i,元素e 功能:位置i后插时间复杂度O(n)[加⼊了查找]若已知指针p指向的后插 O(1)ListDelete(LinkList &L,int i) 参数:单链表L,位置i 功能:删除位置i元素时间复杂度O(n)[加⼊了查找]若已知p指针指向的删除最好是O(1),因为可以与后继结点交换数据域,然后删除后继结点。
最坏是O(n),即从头查找p之前的结点,然后删除p所指结点LocateElem(LinkList L,ElemType e) 参数:单链表L,元素e 功能:查找第⼀个等于e的元素,返回指针时间复杂度O(n)代码:/*Project: single linkeed list (数据结构单链表)Date: 2018/09/14Author: Frank YuInitList(LinkList &L) 参数:单链表L 功能:初始化时间复杂度 O(1)ListLength(LinkList L) 参数:单链表L 功能:获得单链表长度时间复杂度O(n)ListInsert(LinkList &L,int i,ElemType e) 参数:单链表L,位置i,元素e 功能:位置i后插时间复杂度O(n)[加⼊了查找]若已知指针p指向的后插 O(1)ListDelete(LinkList &L,int i) 参数:单链表L,位置i 功能:删除位置i元素时间复杂度O(n)[加⼊了查找]若已知p指针指向的删除最好是O(1),因为可以与后继结点交换数据域,然后删除后继结点。
[转载整理]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 }。
单链表数据结构
插入
if (p != NULL && j == i-1) { // 找到第i个结点
s = (LinkList) malloc ( sizeof (LNode)); // 生成新结点
s->data = e;
// 数据域赋值
s->next = p->next; //新结点指针指向后一结点
p->next = s; return OK;
6、销毁
4.6 销毁操作
while(L) { p = L->next; free(L); L=p;
// p指向第一结点(头节点为“哑结点”) // 释放首结点 // L指向p
}
// 销毁完成后,L为空(NULL)
算法的时间复杂度为:O(ListLength(L))
判空 求表长
4.7 其它操作
if(L->next==NULL) return TRUE; // 空
5、清空
4.5 清空操作
while (L->next) { p = L->next; L->next = p->next; free(p);
// p指向当前结点 // 头结点指向当前结点的后结点 // 释放当前结点内存
}
// 清空完成后,仍保留头结点L
算法的时间复杂度为:O(ListLength(L))
点。
5.1.2 逆序建立单链表
①建立一个带头结点的空单链表;
②输入数据元素ai,建立新结点p, 并把p插入在头结点之后成为第一个 结点。
③重复执行②步,直到完成单链表的 建立。
a1
a2 a1
创建出来的链表 点顺序与插入操作
顺序相反。
单链表的基本操作实验问题与对策
单链表的基本操作实验问题与对策单链表是一种非常基础且常见的数据结构,被广泛应用于计算机科学和相关领域中。
它通过使用一系列节点来存储元素,每个节点都包含一个值和一个指向下一个节点的指针。
这些节点以线性方式连接,形成了一个单向链表。
在进行单链表的基本操作实验时,可能会遇到一些常见的问题和挑战。
例如,在进行插入操作时,可能会出现指针错误或内存分配失败的问题。
在删除操作中,可能会遇到无法找到指定元素或无法正确更新节点指针的问题。
在进行查找操作时,可能会遇到查找效率低下或无法找到特定元素的问题。
而在遍历操作中,可能会遇到指针断裂或无限循环的问题。
为了解决这些问题,我们可以采取一些对策。
例如,在进行插入操作时,我们可以使用更高效的数据结构或算法来避免指针错误和内存分配失败的问题。
在删除操作中,我们可以使用更精确的查找算法来找到指定元素并正确更新节点指针。
在进行查找操作时,我们可以使用更优化的查找算法或数据结构来提高查找效率并找到特定元素。
而在遍历操作中,我们可以使用更安全的遍历算法来避免指针断裂和无限循环的问题。
总之,单链表是一种非常有用的数据结构,在进行基本操作实验时可能会遇到一些问题和挑战。
但只要我们采取适当的对策,就可以有效地解决这些问题并更好地应用单链表这种数据结构。
问题1:插入节点时如何确保正确的位置?对策:在插入节点之前,需要遍历链表以找到正确的位置。
可以使用循环来遍历链表,确保插入的位置是正确的。
另外,可以考虑维护一个指向前一个节点的指针,以便在插入时更容易操作。
问题2:如何删除节点?对策:删除节点时,需要找到待删除节点的前一个节点,并将其指针指向待删除节点的下一个节点,然后释放待删除节点的内存。
确保在删除节点之前释放内存,以避免内存泄漏。
问题3:如何遍历链表?对策:遍历链表通常需要使用循环,从链表的头节点开始,沿着指针依次访问每个节点,直到达到链表的末尾。
可以使用循环结构来实现遍历,或者使用递归方法。
数据结构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。
单链表应用示例
学生成绩管理以单链表作为存储结构,设计和实现某班某门课程成绩管理的完整程序。
程序要求完成如下功能:(1)创建成绩链表,学生数据包含学生的学号、姓名和成绩。
(2)可以在指定学号学生前插入学生成绩数据。
(3)可以删除指定学号的学生数据。
(4)可以计算学生的总数。
(5)可以按学号和姓名查找学生。
(6)可以显示所有学生的成绩。
(7)可以把学生成绩按从高到低的顺序排列。
此处的设计思想基本与顺序表相同,只是对保存学生成绩的线性表采用不同的存储结构实现。
本例中用到的学生数据也是程序运行时由用户从键盘输入,保存到一个单链表中。
学生结构体类型的定义与顺序表应用举例处的定义相同,用C语言描述如下:typedef struct Student /*学生类型定义*/{ int score; /*成绩*/char sno[5],sname[8]; /*学号,姓名*/}Student;当学生的学号为“#”时,也是表示数据输入的结束。
单链表中保存的数据元素均为学生Student类型,则单链表定义如下:typedef struct Node /*结点类型定义*/{ Student studentInfo; /*学生信息*/struct Node *next; /*指向后继元素的指针域*/}LinkList;对学生的成绩按从高到低排序时,使用的也是直接插入排序思想。
此外,为了排序后还能在原单链表上继续进行操作,这里是把单链表中的内容复制到一个新单链表中,对新单链表排序,原单链表不变。
下面是以单链表作为存储结构实现的学生某门课程成绩管理的完整C语言程序。
#include<string.h>#include<malloc.h>#include <stdlib.h>#include <stdio.h>typedef struct Student /*学生类型定义*/{ int score; /*成绩*/char sno[5],sname[8]; /*学号,姓名*/}Student;typedef struct Node /*结点类型定义*/{ Student studentInfo; /*学生信息*/struct Node *next; /*指向后继元素的指针域*/}LinkList;void display(LinkList *p) /*在屏幕上显示一个学生的成绩信息*/{ printf("\n\n\nno\t\tname\t\tscore: ");printf("\n%s",p->studentInfo.sno); /*打印学号*/printf("\t\t ");printf("%s",p->studentInfo.sname); /*打印姓名*/printf("\t\t ");printf("%-4d\n",p->studentInfo.score); /*打印成绩*/}void displayAll(LinkList *L) /*在屏幕上显示所有学生的成绩信息*/ { LinkList *p;p=L->next;printf("\n\n\nno\t\tname\t\tscore: ");while(p){ printf("\n%s",p->studentInfo.sno); /*打印学号*/printf("\t\t ");printf("%s",p->studentInfo.sname); /*打印姓名*/printf("\t\t ");printf("%-4d\n",p->studentInfo.score);/*打印成绩*/p=p->next;}}LinkList *inputdata( ) /*输入学生信息*/{ LinkList *s=NULL ; /*s是指向新建结点的指针*/ char sno[5]; /*存储学号的数组*/printf("\n ");printf(" no: ");scanf("%s",sno); /*输入学号*/if(sno[0]=='#') /*#结束输入*/return s;s=( LinkList *)malloc(sizeof(LinkList));strcpy(s->studentInfo.sno,sno);if(strlen(sno)>4) /*如果sno字符个数大于等于5,因为字符串没有'\0'结束标志,在读数据时将把姓名字符一起读到sno数组,因此做了如下处理*/ s->studentInfo.sno[4]='\0';printf(" name: ");scanf("%s",s->studentInfo.sname); /*输入姓名*/printf("score: ");scanf("%d",&s->studentInfo.score);/*输入成绩*/return s;}LinkList *createTailList( ) /*以尾插法建立带头结点的学生信息单链表*/{ LinkList *L,*s, *r; /*L头指针,r尾指针,s是指向新建结点的指针*/ L=( LinkList *)malloc(sizeof (LinkList)); /*建立头结点,申请结点存储空间*/r=L; /*尾指针指向头结点*/printf("\请输入学生成绩,当学号no为\"#\"时结束:\n\n ");while (1) /*逐个输入学生的成绩*/{ s=inputdata( );if(!s) break; /*s为空时结束输入*/r->next=s; /*把新结点插入到尾指针后*/r=s; /*r 指向新的尾结点*/ }r->next=NULL; /*尾指针的指针域为空*/displayAll(L); /*显示所有学生信息*/return L;}Void locateElemByno(LinkList *L, char ch[5]) /*按学号查找学生的算法*/{ LinkList *p=L->next; /*从第一个结点开始查找*/ while ( p && (strcmp(p->studentInfo.sno,ch)!=0))/*p不空且输入学号与链表中学号不等*/ p = p ->next;if (!p){ printf("\n\n\tDon't find the student!\n" );}else{ display(p); /*显示查找到的学生信息*/}}void locateElemByname(LinkList *L, char sname[8])/*按姓名查找学生的算法*/{ LinkList *p=L->next; /*从第一个结点开始查找*/ while ( p&& (strcmp(p->studentInfo.sname,sname)!=0)) /*p不空且输入姓名与链表中姓名不等*/ p = p ->next;if (!p){ printf("\n\n\tDon't find the student!\n" ); }else{display(p); /*显示查找到的学生信息*/}}int lengthList (LinkList *L) /*求学生总人数的算法*/{ LinkList * p=L->next; /* p指向第一个结点*/int j=0;while (p){ p=p->next; j++ ;} /* p所指的是第j 个结点*/return j;}void insertElem ( LinkList *L, char ch[5]) /*在带头结点的单链表L中指定学号前插入学生*/ { LinkList *p,*s;p=L; /*从头结点开始查找学号为ch的结点的前趋结点p */while ((p->next) && (strcmp(p->next->studentInfo.sno,ch)!=0))p = p ->next;s=inputdata(); /*输入欲插入学生信息*/s->next=p->next;p->next=s;}void deleteElem (LinkList *L, char ch[5]) /*删除给定学号的学生信息的算法*/{ LinkList *p,*q;p=L;while ( (p->next)&&(strcmp(p->next->studentInfo.sno,ch)!=0 )){ p=p->next; /*从头结点开始查找学号为ch的结点的前趋结点p*/}if (!p->next) /* 已经扫描到表尾也没找到*/{ printf("\n\n\tDon't find the student!\n" );}else{ q=p->next; /*q指向学号为ch的结点*/printf("\n\ndeleted student's information:");display(q);p->next=q->next; /*改变指针*/free(q); /*释放q占用空间*/printf("\n\nall student's information :");displayAll(L);}}void insertSort(LinkList *L) /*用直接插入排序思想把学生的成绩按从高到低排序,结果保存在新有序链表中,原链表不变*/{ L inkList *L1,*p; /*L1有序链表的表头,p插入位置前结点*/ LinkList *q,*s; /*q欲插入L1中的结点*/int len;len=lengthList (L) ;L1=( LinkList *)malloc(sizeof (LinkList)); /*建立头结点,申请结点存储空间*/if (L->next) /*链表L非空*/{ /*生成有序链表的第一个结点*/s=( LinkList *)malloc(sizeof (LinkList)); /*建立结点,申请结点存储空间*/strcpy(s->studentInfo .sno ,L->next->studentInfo.sno);strcpy(s->studentInfo .sname,L->next->studentInfo.sname);s->studentInfo .score =L->next->studentInfo.score;s->next =NULL;L1->next=s; /*只有原单链表的第一个结点的有序链表L1*/q=L->next->next; /*原单链表的第二个结点,q即要插入有序链表L1中的结点*/ }else{ printf("\nthe student link list is empty\n");return;}while(q) /*链表L中有结点*/{ p=L1 ; /*从链表L1的第一个结点开始比较*/while((p->next) && (p->next->studentInfo.score>=q->studentInfo.score))p=p->next ; /*查找插入位置前结点*//*生成欲插入有序链表中的结点*/s=( LinkList *)malloc(sizeof (LinkList));/*建立结点,申请结点存储空间*/strcpy(s->studentInfo .sno ,q->studentInfo.sno);strcpy(s->studentInfo .sname ,q->studentInfo.sname);s->studentInfo .score =q->studentInfo.score;if(!p->next) /*p是有序链表的最后一个结点*/{ s->next =NULL ;p->next =s;}else{ s->next =p->next ;p->next =s;}q=q->next; /*下一个欲插入有序链表的结点*/ }/*while(!q)*/displayAll(L1); /*显示生成的有序链表*/}void main(){ printf("=============================================\n\n");printf(" 带头结点的学生成绩管理程序\n\n");printf("=============================================\n\n");LinkList *L;char ch[5],sname[8];int b=1;while(b){ int a;printf("\n\n");printf(" <1>创建(带头尾插)<2>指定学号前插入<3>按学号删除\n ");printf("<4>计算学生总数<5> 按学号查找<6> 按姓名查找\n");printf(" <7>显示所有学生<8>成绩排序<9> 退出\n");printf("\n请输入功能选项:");scanf("%d",&a);switch(a){case 1:L=CreateTailList();break;case 2:printf("\n输入欲在哪个学号前插入数据:");scanf("%s",ch);insertElem(L, ch) ;break;case 3:printf("\n输入欲删除学生的学号:");scanf("%s",ch);deleteElem(L, ch) ;break;case 4:printf(" \n学生总数为:%d \n",lengthList (L) );break;case 5:printf("\n输入欲查找学生的学号:");scanf("%s",ch);locateElemByno(L, ch) ;break;case 6:printf("\n输入欲查找学生的姓名:");scanf("%s",sname);locateElemByname(L, sname );break;case 7:displayAll(L);break;case 8:insertSort(L);break;case 9:printf("\n已退出\n");b=0;break;};}}上机运行程序后,程序执行结果如图2.31(a)~(i)所示。
数据结构 实验一:实现单链表各种基本运算的算法
- 1 -实验一:实现单链表各种基本运算的算法一、 实验目的1、 掌握单链表存储结构的类型定义;2、 实现单链表各种基本运算的算法。
二、 实验环境1、 Windows 操作系统;2、 Visual C++ 6.0三、 实验内容实现单链表各种基本运算的算法。
四、 概要设计1.存储结构的类型定义:Typedef struct LNode{ElemType data;Struct LNode *next;}LinkList;2.单链表示意图:3.项目组成图:4.algo2_2.cpp 的程序文件包含的函数原型及功能:InitList(LinkList *&L) 初始化单链表LDestroyList(LinkList *&L) 释放单链表LListEmpty(LinkList *L)判断单链表L 是否为空表ListLength(LinkList *L)返回单链表L 的元素个数DispList(LinkList *L)输出单链表LGetElem(LinkList *L,int i,ElemType &e)获取单链表L 的第i 个元素LocateElem(LinkList *L,ElemType e)在单链表L 中查找元素eListInsert(LinkList *&L,int i,ElemType e)在单链表L 中的第i 个位置上插入元素e…… head a 1 a 2 a 3 a n ∧ListDelete(LinkList *&L,int i,ElemType &e)在单链表L中删除第i个元素5.exp2_2.cpp程序文件简介:InitList(LinkList *&L) 初始化单链表LDestroyList(LinkList *&L) 释放单链表LListEmpty(LinkList *L) 判断单链表L是否为空表ListLength(LinkList *L) 返回单链表L的元素个数DispList(LinkList *L) 输出单链表LGetElem(LinkList *L,int i,ElemType &e) 获取单链表L的第i个元素LocateElem(LinkList *L,ElemType e) 在单链表L中查找元素eListInsert(LinkList *&L,int i,ElemType e) 在单链表L中的第i个位置上插入元素e ListDelete(LinkList *&L,int i,ElemType &e) 在单链表L中删除第i个元素6.proj2-2的项目的模块结构:在文件algo2-2中,(1)定义单链表结构类型;(2)初始化单链表(3)定义释放单链表的函数(4)定义判断单链表是否为空的函数(5)定义返回单链表元素个数的函数(6)定义输出单链表的函数(7)定义获取第i个元素的函数(8)定义查找元素的函数(9)定义插入元素的函数(10)定义删除元素的函数在文件exp2-2中分别调用algo2-2中所定义的函数7.函数调用关系图:五、详细设计源代码清单见附录。
pta 单链表基本操作
pta 单链表基本操作
单链表是一种常见的数据结构,由一个个节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。
基本操作包括以下几种:
1. 创建链表:创建一个空链表,即创建一个头节点。
2. 插入节点:在链表的任意位置插入一个节点。
- 头部插入:将新节点作为新的头节点,其指针指向原头节点。
- 中间插入:将新节点插入到指定位置的节点之前,其指针指向指定位置的节点。
- 尾部插入:找到链表尾部节点,将新节点插到尾部节点的后面。
3. 删除节点:在链表中删除指定节点。
- 头部删除:将头节点删除,将头节点的下一个节点作为新的头节点。
- 中间删除:找到指定节点的前驱节点,将前驱节点的指针指向指定节点的后继节点。
- 尾部删除:找到尾部节点的前驱节点,将前驱节点的指针设为NULL。
4. 查找节点:在链表中查找指定数据的节点。
- 遍历链表,逐个比较节点的数据元素,直到找到指定数据或遍历到末尾节点。
5. 修改节点:在链表中修改指定节点的数据。
- 遍历链表,找到指定节点,修改其数据元素。
6. 遍历链表:按顺序遍历链表中的所有节点,进行相应操作。
这些是单链表的基本操作,可以根据需求进行组合和扩展。
C#数据结构之单链表(LinkList)实例详解
C#数据结构之单链表(LinkList)实例详解本⽂实例讲述了C#数据结构之单链表(LinkList)实现⽅法。
分享给⼤家供⼤家参考,具体如下:这⾥我们来看下“单链表(LinkList)”。
在上⼀篇《》的最后,我们指出了:顺序表要求开辟⼀组连续的内存空间,⽽且插⼊/删除元素时,为了保证元素的顺序性,必须对后⾯的元素进⾏移动。
如果你的应⽤中需要频繁对元素进⾏插⼊/删除,那么开销会很⼤。
⽽链表结构正好相反,先来看下结构:每个元素⾄少具有⼆个属性:data和next。
data⽤来存放数据,⽽next⽤来指出它后⾯的元素是谁(有点“指针”的意思)。
链表中的元素,通常也称为节点Node,下⾯是泛型版本的Node.csnamespace 线性表{public class Node<T>{private T data;private Node<T> next;public Node(T val, Node<T> p){data = val;next = p;}public Node(Node<T> p){next = p;}public Node(T val){data = val;next = null;}public Node(){data = default(T);next = null;}public T Data{get { return data; }set { data = value; }}public Node<T> Next{get { return next; }set { next = value; }}}}链表在存储上并不要求所有元素按顺序存储,因为⽤节点的next就能找到下⼀个节点,这好象⼀根“⽤珠⼦串成的链⼦”,要找到其中的某⼀颗珠⼦,只要从第⼀颗节点(通常称为Head节点)开始,不断根据next指向找到下⼀个,直到找到需要的节点为⽌。
一元多项式的单链表表示及其运算
一元多项式的单链表表示及其运算
一元多项式的单链表表示是将多项式的每一项以节点的形式存储在链表中,链表的每个节点包含两个数据域,一个表示系数,一个表示指数。
链表中的节点按照指数从大到小的顺序排列,这样可以方便进行多项式的运算。
例如,多项式2x^3 + 3x^2 + 4x + 5可以表示为如下的单链表:
5 -> 4 -> 3 -> 2 -> NULL
其中,每个节点的第一个数据域表示系数,第二个数据域表示指数。
针对这个单链表表示的多项式,可以进行多项式的加法、减法、乘法等运算。
多项式的加法运算可以通过遍历两个链表,按照指数的大小逐个比较,并将相同指数的项系数相加,将不同指数的项加入到结果链表中。
多项式的减法运算可以通过将减数链表中的每个项的系数取相反数,然后调用加法运算。
多项式的乘法运算可以通过遍历两个链表,计算每一项的系数和指数的乘积,将结果项按照指数从大到小的顺序加入到结果链表中。
除了基本的加法、减法和乘法运算外,还可以对多项式进行求导、求积分等运算。
【头歌】单链表的基本操作
【头歌】单链表的基本操作
单链表是一种线性数据结构,由一系列节点组成,每个节点包含数据元素和一个指向下一个节点的指针。
以下是单链表的基本操作:
1. 插入操作:在单链表的指定位置插入一个新节点。
具体步骤如下:
找到要插入的位置的前一个节点;
将新节点插入到前一个节点和当前节点之间;
修改新节点的指针,使其指向当前节点;
修改前一个节点的指针,使其指向新节点。
2. 删除操作:删除单链表中的指定节点。
具体步骤如下:
找到要删除的节点的前一个节点;
将前一个节点的指针指向要删除的节点的下一个节点;
释放要删除的节点的内存。
3. 查找操作:在单链表中查找指定元素。
具体步骤如下:
从头节点开始遍历单链表;
找到与指定元素相等的节点;
返回该节点的位置。
4. 遍历操作:从头节点开始,依次访问单链表中的每个节点。
具体步骤如下:创建一个指针指向头节点;
依次访问指针所指向的每个节点,直到指针为空。
5. 打印操作:打印单链表中的所有元素。
具体步骤如下:
创建一个指针指向头节点;
依次打印指针所指向的每个节点的数据元素,直到指针为空。
以上是单链表的基本操作,通过这些操作可以对单链表进行各种操作,如插入元素、删除元素、查找元素等。
第三章 链表
第三章 链表
第三章 链表
知识点
单链表的结点形式、组织方法和特点 单链表的基本运算和相应的算法 循环链表的组织方法和基本运算算法 双链表的结点形式、组织方法和特点 双链表的基本运算和相应的算法 顺序表与链表比较,各自的优、缺点 链表的应用 用十字链表表示稀疏矩阵
第三章 链表
难点
双链表插入、删除运算的算法 利用链接结构的特点设计有效算法,解决与链表结 构相关的应用问题
第三章 链表
算法分析
此算法的关键是while循环语句,开始时p 指针指向头结点,每一循环都修改指针 值,让它指向下一个结点,同时将计数 链表长度的变量count加1。 这样每循环一次就向后推移一个结点, 直到p所指结点*p的链域值为NULL为止。 空指针NULL起标志的作用,若无此标志, 尾结点链域的值为“无定义”,上述算 法中的while语句在做最后一次判断时将 出现“运行错”,这是应予避免的。
第三章 链表
3.3.2 链队列
链队列需要两个指针,其中队首指针front指向 链表的表头,队尾指针rear指向链表的表尾。 一般插入时只修改队尾结点的指针和队尾指针 rear,删除时只修改队首指针front。当将第一个 元素插入空队列或删除了最后一个元素而使队 列为空时,front和rear都需要修改。 front rear
当需要从单链表上删除结点时,就要通过删 除运算来完成。 删除单链表上一个其值为x的结点的主要操作 是:
1) 用遍历的方法在单链表上找到该结点; 2) 从单链表上删除该结点。
欲从单链表上删除一个结点,需修改该结点 的前一个结点的指针,如下面的图所示。
第三章 链表
q head
p x ∧
假设指针q指向待删除结点的前一个结点,指 针p指向要删除的结点,删除该结点的操作如 下:将该结点的前一个结点*q的链域指向*p 的后继结点(即q->next=p->next)。
单链表的基本概念
插入节点
01
找到插入位置
遍历链表,找到需要插入新节点 的位置。
02
03
创建新节点
调整指针
创建一个新的节点,并设置其数 据域。
将新节点的指针指向原位置的下 一个节点,同时将前一个节点的 指针指向新节点。
删除节点
找到待删除节点
遍历链表,找到需要删除的节点。
调整指针
将待删除节点的前一个节点的指针指向待删除节 点的下一个节点,从而跳过待删除节点。
合并两个有序链表
遍历两个链表,比较当前节点的数据大 小,将较小的节点插入到新链表的末尾。
重复上述过程,直到其中一个链表遍历完成。
将剩余未处理的节点直接链接到新 链表的末尾。
合并两个有序链表
注意事项
1
2
在插入节点时需要注意更新前一个节点的指针。
3
可以使用哑节点来简化头节点的处理过程。
THANKS.
合并两个有序链表
• 问题描述:合并两个有序链表是计算机科学中的一个常见问题,可以使用单链表来表示两个有序序列,通过遍 历两个链表并将节点按照大小插入到新的链表中,得到最终的合并结果。
合并两个有序链表
实现步骤 定义单链表节点结构,包含数据和指向下一个节点的指针。
创建两个有序链表,分别表示要合并的两个序列。
存储空间额外开销
由于每个节点都需要存储指针信息,因此链表相对于数组有一定的 空间开销。
链表的应用场景
动态数据结构
链表适用于需要动态调整大小的数据结构,如实现动态数 组、栈、队列等。
元素插入和删除频繁的场景
链表在元素插入和删除操作上具有优势,适用于需要频繁 进行这些操作的场景,如编辑器的文本处理、网络数据包 的传输等。
数据结构之单链表头插法,尾插法
数据结构之单链表头插法,尾插法数据结构之单链表头插法,尾插法单链表是中的⼀种,单链表的头插法也称前插法。
链表也是线性表的⼀种,与顺序表不同的是,它在内存中不是连续存放的。
在C语⾔中,链表是通过指针相关实现的。
⽽单链表是链表的其中⼀种,关于单链表就是其节点中有数据域和只有⼀个指向下个节点的指针域。
创建单链表的⽅法有两种,分别是头插法和尾插法。
所谓头插法,就是按节点的逆序⽅法逐渐将结点插⼊到链表的头部。
反之尾插法就是按节点的顺序逐渐将节点插⼊到链表的尾部。
相对来说,头插法要⽐尾插法算法简单,但是最后产⽣的链表是逆序的,即第⼀个输⼊的节点实际是链表的最后⼀个节点。
⽽为了习惯,通常⽤尾插法来创建链表。
下⾯的代码就是实现了头插法和尾插法创建头节点//创建头结点Node* Create_List (){//创建头结点Node* list = (Node*) malloc(sizeof(Node) / sizeof(char));if (NULL == list) //检验创建是否成功{return FALSE;}list->next = NULL;return list;}头插法// 头插法int Insert_Last (Node* h, LinkData data){// 判断数据传⼊是否正确if (NULL == h){return FALSE;}// 创建新结点并判断创建是否成功Node* node = (Node*) malloc(sizeof(Node) / sizeof(char));if (NULL == node){return FALSE;}// 给结点成员变量赋值node->data = data;node->next = h->next; // 和头指针的不同:node->next = *h;// 让新结点变为链表的第⼀个节点h->next = node;return TRUE;}尾插法//尾插int Insert_Last(Node* h, LinkData data){if (NULL == h){return FALSE;}// 创建新结点并判断创建是否成功Node* node = (Node*) malloc(sizeof(Node) / sizeof(char));if (NULL == node){return FALSE;}// 给结点成员变量赋值node->data = data;node->next = NULL;// 让新结点变为链表的最后⼀个节点Node* tmp = h;while(tmp->next){tmp = tmp->next;}//找到链表的尾节点并令尾节点指向nodetmp->next = node;return TRUE;}扩充中间插⼊//中间插⼊法int Insert_Pos(Node *h, int pos, LinkData data){//判断链表是否存在if (NULL == h){return FALSE;}Node* tmp = h;int i;for (i = 0; i < pos - 1; i++){if (NULL == tmp){break;}tmp = tmp->next;}//判断tmp是否存在if (NULL == tmp){printf ("插⼊位置越界");return FALSE;}Node* node = (Node*) malloc(sizeof(Node) / sizeof(char)); if (NULL == node){return FALSE;}node->data = data;node->next = tmp->next;tmp->next = node;return TRUE;}。
递归求解单链表中的结点个数
递归求解单链表中的结点个数递归求解单链表中的节点个数在计算机科学中,递归是一种解决问题的方法,它把一个问题分解为更小的子问题,并通过不断调用自身解决这些子问题。
本文将介绍如何使用递归的方法来求解单链表中的节点个数。
一、递归的基本原理递归是一种解决问题的方法,它通过将原问题划分为同样结构的子问题来解决。
递归函数在执行过程中调用自身,并通过不断缩小问题规模来解决问题。
在递归函数中,需要定义递归终止条件,以防止无限递归。
二、单链表单链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据域和指向下一个节点的指针。
单链表的最后一个节点指向空节点,表示链表的结束。
三、递归求解单链表节点个数的方法为了递归求解单链表中的节点个数,我们可以定义一个递归函数。
该函数的作用是计算从当前节点开始的子链表中的节点个数,并将结果返回。
具体步骤如下:1. 如果当前节点为空节点,则返回0;2. 否则,递归调用函数,计算从当前节点的下一个节点开始的子链表中的节点个数,并将结果保存;3. 返回子链表中的节点个数加1。
通过上述步骤,我们可以使用递归求解单链表中的节点个数。
下面是一个示例代码:```pythondef count_nodes(node):if node is None:return 0else:return count_nodes(node.next) + 1```四、递归求解单链表节点个数的示例为了更好地理解递归求解单链表节点个数的方法,我们可以使用一个简单的示例来演示。
假设我们有一个包含5个节点的单链表,每个节点的数据域依次为1、2、3、4、5。
下面是求解节点个数的示例代码:```pythonclass Node:def __init__(self, data):self.data = dataself.next = Nonedef count_nodes(node):if node is None:return 0else:return count_nodes(node.next) + 1 # 创建单链表head = Node(1)node2 = Node(2)node3 = Node(3)node4 = Node(4)node5 = Node(5)head.next = node2node2.next = node3node3.next = node4node4.next = node5# 求解节点个数count = count_nodes(head)print("节点个数为:", count) # 输出结果为5```在上述示例中,我们首先定义了一个`Node`类来表示单链表的节点。
数据结构单链表中确定单链表中的最小数的原理
数据结构单链表中确定单链表中的最小数的原理
在单链表中确定最小数的原理可以通过遍历整个链表来实现。
具体步骤如下:
1. 声明一个变量min_value,并初始化为当前链表的第一个节点的值。
2. 从链表的第二个节点开始,依次遍历链表的每个节点。
3. 对每个节点的值进行比较,如果节点的值比min_value小,则将min_value更新为当前节点的值。
4. 继续遍历链表,直到遍历完所有节点。
5. 遍历完整个链表后,min_value就是链表中的最小值。
该算法的时间复杂度为O(n),其中n是链表中的节点数量。
由于需要遍历整个链表,因此算法的性能取决于链表的长度。
单链表实验报告总结
单链表实验报告总结单链表实验报告总结篇一:单链表实验报告实验一线性表基本操作的编程实现 --线性表在链表存储下的主要操作实现班级:T523-1 姓名:王娟学号:33 完成日期:201X.0 4.04 地点:5502 学时:2学时一、需求分析【实验目的】通过本次实验,对课堂上线性表的知识进行巩固,进一步熟悉线性表的链接存储及相应的基本操作;并熟练掌握VC++6.0操作平台,学会调试程序,以及编写电子实验报告【实验要求】编写线性表的基本操作,有构造线性表,线性表的遍历,插入,删除,查找,求表长等基本功能,在此基础上能够加入DS下的图形界面以及学会文件的操作等功能,为以后的学习打下基础。
【实验任务】(1).线性表基本操作的编程实现,掌握线性表的建立、遍历、插入、删除等基本操作的编程实现,也可以进一步编程实现查找、逆序、排序等操作,存储结构可以在顺序结构或链表结构中任选,可以完成部分主要功能,也可以用菜单进行管理完成大部分功能。
还鼓励学生利用基本操作进行一些更实际的应用型程序设计。
(2).用菜单管理,把线性表的顺序存储和链表存储的数据插入、删除运算进行程序实现。
建议实现键盘数据输入实现改实验的通用性。
为了体现功能的正常性,至少要编制遍历数据的函数.(3).注意事项:开发语言使用C++,尽量使用面向对象的思想和实现方法,可以改编成应用软件. 【实验类型】验证型实验二、概要设计需要实现线性表的以下功能:1、创建单链表2、删除链表中的某个结点3、输出单链表(遍历)4、释放结点所占空间5、查找第i个结点6、插入一个结点7、求链表的长度二、详细设计(1).数据结构线性表的线性结构觉决定了它的性质:数据元素之间是一种线性关系,数据元素一个接一个的排列,除了最后一个数据,其他的数据面临的下一个数据有且仅有一个。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
# include "stdlib.h"
# include "malloc. h"
struct node /*节点的数据结构* /
{
int num;
char str[20];
struct node *next;
} ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * / main( )
{
/ *函数声明* /
struct node *creat();
struct node *insert();
struct node *delet();
void print( );
struct node *head;
char str[20];
int n;
head=NULL; /*做空表* /
head=creat (head); / *调用函数创建以head 为头的链表* / p r i n t ( h e a d ) ;/ *调用函数输出节点* /
printf("\n input inserted num,name:\n");
gets(str); /*输入学号* /
n=atoi (str);
gets(str); /*输入姓名* /
head=insert (head, str, n); 将/*节点插入链表*/
print (head);/ *调用函数输出节点*/
printf("\n input deleted name:\n");
gets(str); /*输入被删姓名* /
head=delet(head,str); /调*用函数删除节点*/
print (head); /*调用函数输出节点* /
r e t u r n ;
}
/ * * * * * * * * * * * * * * * * * * * * * * /
/ * * * 创建链表* * * * * * * * * * * * /
struct node *creat(struct node *head)
{
char temp[30];
struct node *pl,*p2;
pl=p2=(struct node*) malloc(sizeof(struct node));
printf ("input num, name: \n;")
printf("exit:double times Enter!\n");
g e t s ( t e m p ) ;
gets (p1->str);
pl->num=atoi (temp);
p l - > n e x t = N U L L ;
while (strlen (pl->str)>0
{
if (head==NULL) head=pl;
else p2->next=p1;
P 2 = p l ;
pl=(struct node *)malloc(sizeof(struct node)); printf ("input num, name: \n");
printf("exit:double times Enter!\n");
g e t s ( t e m p ) ;
gets(pl ->str);
p1->num=atoi (temp);
P 1 - > n e x t = N U L L ;
}
return head;
}
/ * * * * * * * * * * * * * * * * * * * * /
/ * * * * * * * * * * 插入节点* * * * * * * * * * / struct node *insert (head, pstr,n);
struct node *head;
char *pstr;
int n;
{
struct node *pl,*p2,*p3;
p1=(struct node*)malloc(sizeof(struct node)); strcpy (p1->str, pstr);
p 1 - > n u m = n ;
p 2 = h e a d ;
i f ( h e a d = = N U L L )
{
h e a d = p l ; p l - > n e x t = N U L L ;
}
e l s e
{
while (n>p2->num&&p2->next!=NULL)
{
p 3 = P 2
p 2 = p 2 - > n e x t ;
}
if (n<=p2->num)
if (head==p2)
{
h e a d = p l ;
p l - > n e x t = p 2 ;
}
else
{
p 3 - > n e x t = p l ;
p l - > n e x t = p 2 ;
}
else
{
p 2 - > n e x t = p l ;
p l - > n e x t = N U L L ;
}
}
r e t u r n ( h e a d ) ;
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * * * * * 删除节点* * * * * * * * * * * * * /
struct node *delet (head, pstr)
struct node *head;
char *pstr;
{
struct node *temp,*p;
t e m p = h e a d ;
if (head==NULL)
printf("\nList is null!\n");
else
{
t e m p = h e a d ;
while (strcmp(temp->str,pstr)!=O&&temp->next!=NULL) {
p = t e m p ;
t e m p = t e m p - > n e x t ,
}
i f ( s t r c m p ( t e m p - > s t r , p s t r ) = = 0 )
{
if (temp== head)
{
h e a d = h e a d - > n e x t ;
f r e e ( t e m p ) ;
}
else
{
p->next =temp->next;
printf("delete string :%s\n",temp->str);
f r e e ( t e m p ) ;
}
}
else printf("\nno find string!\n");
}
return(head);
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * * * * * * * * * * 链表各节点的输出* * * * * * * * * * /
void print (struct node *head)
{
struct node *temp;
t e m p = h e a d ;
printf("\n output strings:\n");
while (temp!=NULL)
{
p r i n t f ( " \ n % d - - - - % s \ n " , t e m p - > n u m ,t e m p - > s t r ) ;t e m p = t e m p - > n e x t ;
}
r e t u r n ;
}。