数据结构之链表

什么是链表

简单的说,链表就是由多个结点离散分配,彼此通过指针相连,每个结点只有一个前驱结点和后继结点。首节点无前驱结点,为结点无后继结点的一种存储结构。

链表的结构

头结点:链表的第一个有效结点前面的结点,头结点并不存放有效数据,也就是数据域为空,加头结点的主要目的是为了方便链表的操作。

首节点:链表的第一个有效结点,结点包含数据域和指针域。

尾结点:尾结点的指针域为空。

头指针:指向头结点的指针变量,它存放了头结点的地址(在这里注意一下,指针变量存放的是地址,也就是说头指针存放的是头结点的地址,一般通过头指针对链表进行操作)。

具体实现

#includestdio.h#includemalloc.h#includestdlib.h//定义链表节点typedefstructNode{intdata;//数据域structNode*pNext;//指针域}NODE,*PNODE;//NODE等价于structNode,PNODE等价于structNode*

//函数声明PNODEcreateLinkList(void);//创建链表的函数voidtraverseLinkList(PNODEpHead);//遍历链表的函数boolisEmpty(PNODEpHead);//判断链表是否为空的函数intgetLength(PNODEpHead);//获取链表长度的函数boolinsertElement(PNODEpHead,intpos,intval);//向链表中插入元素的函数,三个参数依次为链表头结点、要插入元素的位置和要插入元素的值booldeleteElement(PNODEpHead,intpos,int*pVal);//从链表中删除元素的函数,三个参数依次为链表头结点、要删除的元素的位置和删除的元素的值voidsort(PNODEpHead);//对链表中的元素进行排序的函数(基于冒泡排序)intmain(void){intval;//用于保存删除的元素PNODEpHead=NULL;//PNODE等价于structNode*pHead=createLinkList();//创建一个非循环单链表,并将该链表的头结点地址赋给pHeadtraverseLinkList(pHead);//调用遍历链表的函数if(isEmpty(pHead))printf(链表为空!\n);elseprintf(链表不为空!\n);printf(链表的长度为:%d\n,getLength(pHead));//调用冒泡排序函数sort(pHead);//重新遍历traverseLinkList(pHead);//向链表中指定位置处插入一个元素if(insertElement(pHead,4,30))printf(插入成功!插入的元素为:%d\n,30);elseprintf(插入失败!\n);//重新遍历链表traverseLinkList(pHead);//删除元素测试if(deleteElement(pHead,3,val))printf(元素删除成功!删除的元素是:%d\n,val);elseprintf(元素删除失败!\n);

traverseLinkList(pHead);system(pause);return0;}PNODEcreateLinkList(void){intlength;//有效结点的长度inti;intvalue;//用来存放用户输入的结点的值//创建了一个不存放有效数据的头结点PNODEpHead=(PNODE)malloc(sizeof(NODE));if(NULL==pHead){printf(内存分配失败,程序退出!\n);exit(-1);}PNODEpTail=pHead;//pTail始终指向尾结点pTail-pNext=NULL;//清空指针域printf(请输入您想要创建链表结点的个数:len=);scanf(%d,length);for(i=0;ilength;i++){printf(请输入第%d个结点的值:,i+1);scanf(%d,value);PNODEpNew=(PNODE)malloc(sizeof(NODE));if(NULL==pHead){printf(内存分配失败,程序退出!\n);exit(-1);}pNew-data=value;//向新结点中放入值pTail-pNext=pNew;//将尾结点指向新结点pNew-pNext=NULL;//将新结点的指针域清空pTail=pNew;//将新结点赋给pTail,使pTail始终指向为尾结点}returnpHead;}voidtraverseLinkList(PNODEpHead){PNODEp=pHead-pNext;while(NULL!=p){printf(%d,p-data);p=p-pNext;}printf(\n);return;}boolisEmpty(PNODEpHead){if(NULL==pHead-pNext)returntrue;elsereturnfalse;}intgetLength(PNODEpHead){PNODEp=pHead-pNext;//指向首节点intlen=0;//记录链表长度的变量while(NULL!=p){len++;p=p-pNext;//p指向下一结点}returnlen;}voidsort(PNODEpHead){intlen=getLength(pHead);//获取链表长度inti,j,t;//用于交换元素值的中间变量PNODEp,q;//用于比较的两个中间指针变量for(i=0,p=pHead-pNext;ilen-1;i++,p=p-pNext){for(j=i+1,q=p-pNext;jlen;j++,q=q-pNext){if(p-dataq-data){t=p-data;p-data=q-data;q-data=t;}}}return;}boolinsertElement(PNODEpHead,intpos,intval){inti=0;PNODEp=pHead;//判断p是否为空并且使p最终指向pos位置的结点while(NULL!=pipos-1){p=p-pNext;i++;}if(NULL==p

ipos-1)returnfalse;//创建一个新结点PNODEpNew=(PNODE)malloc(sizeof(NODE));if(NULL==pNew){printf(内存分配失败,程序退出!\n);exit(-1);}pNew-data=val;//定义一个临时结点,指向当前p的下一结点PNODEq=p-pNext;//将p指向新结点p-pNext=pNew;//将q指向之前p指向的结点pNew-pNext=q;returntrue;}booldeleteElement(PNODEpHead,intpos,int*pVal){inti=0;PNODEp=pHead;//判断p是否为空并且使p最终指向pos结点while(NULL!=p-pNextipos-1){p=p-pNext;i++;}if(NULL==p-pNext

ipos-1)returnfalse;//保存要删除的结点*pVal=p-pNext-data;//删除p后面的结点PNODEq=p-pNext;p-pNext=p-pNext-pNext;free(q);q=NULL;returntrue;}

结尾语

上面实现的主要是单链表,另外还有双链表、循环链表、非循环链表等其他几种常见链表。双链表的特殊性表现在每个基本结点有两个指针域;循环链表的特性主要表现在,在循环链表中,通过任何一个结点可以找到其他所有结点









































早期白癜风症状图片
治白癜风哈尔滨哪家医院好



转载请注明:http://www.92nongye.com/txjg/204613904.html

  • 上一篇文章:
  •   
  • 下一篇文章: