10.删除线性表某一位置的元素
//删除线性表某一位置的元素StatusDeleteList_L(LinkList&L,intindex) { LinkListp,q; p=L; //将线性表的头结点赋值给pintcount=0; //计数器while(p->next&&count<index-1){ p=p->next; count++; //此时p一直指向第count个结点 } if(!(p->next) ||count>index-1){ //越界判断 printf("当前位置无法删除元素\n"); returnERROR; } q=p->next; p->next=q->next; free(q); q=NULL; printf("当前位置元素已删除\n"); returnOK; }
删除某一结点的思路仍然是从头结点开始遍历,找到要删除的结点的位置的前一个结点,此时p就是要删除结点位置的前一个结点。将p的后一个结点赋值给q,此时q就是要删除的结点,将q的下一个结点与p的下一个结点连接,释放q结点,完成删除操作。
11.求线性表某一元素的前驱
//求线性表某一元素的前驱 StatusPriorElem_L(LinkListL,intindex) { LinkListp; intcount=0; //count为计数器 p=L; while(p->next&&count<index-1){ //寻找第index-1个结点 p=p->next; //p一直指向第count个结点 count++; } if(!(p->next) ||count>index-1){ //越界判断 printf("当前位置无法求该元素的前驱\n"); returnERROR; } if(p!=L) //如果要获取第一个元素的前驱,就是获取头结点数据域的值 printf("该元素的前驱为:%d\n",p->data); elseprintf("该位置的前驱是头结点\n头结点的数据域中存储的值为:%d\n",p->data); returnOK; }
和删除结点的思路完全一致,只不过求前驱时不需要进行删除结点,在循环中控制循环条件使p在index - 1位置结束循环,此时p指向的就是第index的前驱,直接将p结点的数据域输出即可
12.求线性表某一元素的后继
//求线性表某一元素的后继 StatusNextElem_L(LinkListL,intindex) { LinkListp; intcount=0; p=L->next; while(p&&count<index){ //不断遍历寻找第index之后的结点 p=p->next; //p一直指向index-1的后一个结点 count++; } //!p的目的是为了确保i不大于表长-1,count>index的目的是为了确保index不小于0 if(!p||count>index){ //越界判断printf("当前位置无法求该元素的后继\n"); returnERROR; } printf("该元素的后继为:%d\n",p->data); }
在声明LinkList类型变量p时将L的首元结点赋值给p,在循环中p一直指向第index的下一个结点,所以直接将p结点的数据域输出即可
13.打印线性表
//打印线性表StatusPrintList_L(LinkListL) { if(!L){ //如果线性表不存在,返回ERROR printf("线性表不存在,无法打印\n"); returnERROR; } LinkListp; p=L->next; //将L的首元结点赋值给p ,为了不将头结点打印出来 while(p){ printf(" %d",p->data); //将p结点的数据域输出 p=p->next; //结点不断的向后移动 } printf("\n"); returnOK; }
打印单链表的思路也是进行对单链表的遍历,在遍历的过程中将每个结点的数据域中存储的值输出
运行结果演示:
为了方便演示,在这里为单链表一次赋值为1,2,3,4,5
构造一个空的头结点
赋值操作
判断此时线性表是否为空
获取单链表的长度
获取2号位置的元素
在3号位置插入520并打印单链表
获取此时单链表的长度
删除3号位置的元素并打印单链表
求3号位置元素的前驱和后继
重置单链表并获取长度以及判断是否为空表
销毁单链表并进行赋值和判断是否为空
以上便是线性表链式表示和实现,由于链表在空间的合理利用上和插入、删除是不需要移动等的优点,因此在很多场合下它是线性表的首选存储结构。然而,它也存在着实现某些基本操作的缺点,比如:求线性表长度时不如顺序存储结构…
源码:
//函数结果状态代码 //代码中出现TRUE相当于出现了1 //出现FALSE相当于出现了0 //出现OK相当于出现了1 //出现ERROR相当于出现了0 typedefintStatus; //定义函数的返回状态 typedefintElemType; typedefstructLNode{ ElemTypedata; //数据域 structLNode*next; //指针域,指向一整个结点(结构体,该结构体中包含数据域和指针域) }LNode , *LinkList; //* LinkList是结点的类型,在之后的代码中出现了它就相当于出现了指向这个结点的指针 //构造一个空的头结点 StatusInitList_L(LinkList&L){ //之前因为没有输入"&"符号,没有使用引用传递也就意味着没有开辟了新的内存空间,所以在之后赋值的时候会出现无法赋值的情况 L= (LinkList)malloc(sizeof(LNode)); //产生头结点,并使L指向该头结点(L也称头指针)if(!L) returnERROR; //如果存储空间分配失败,返回ERRORL->next=NULL; //将指针域赋值为NULL,在这里要强调一点:"->"是一个整体,它是用于指向结构体子数据的指针 printf("空的头结点创建成功\n"); returnOK; } //对线性表进行赋值 StatusValueList_L(LinkList&L,ElemTypee){ LinkLists,p; p=L; while(p->next){ p=p->next; } s= (LinkList)malloc(sizeof(LNode)); //生成一个新结点 s->data=e; //将e赋值给新结点的数据域 s->next=p->next; //将新结点与后一个结点的地址连接p->next=s; returnOK; } //对线性表进行销毁StatusDistoryList_L(LinkList&L) { /*从头结点开始逐一释放,释放前使p指向头结点,q指向开始释放的结点当开始结点不为空时,执行释放过程先释放头结点,然后将p,q都向后移,依次释放因为q始终是p的后继,所以最后一定是p留到最后,最后释放p*/if(!L){ //如果线性表不存在,返回ERROR printf("线性表不存在\n"); returnERROR; } LinkListq=L->next; //使q指向单链表的首元结点 while(q!=NULL){ //当q结点不为空时一直进入循环 free(L); //释放L结点 L=q; //将q结点赋值给L结点 q=L->next; //将q结点赋值给L结点以后使q结点指向L的下一个结点 } free(L); //此时q的值为NULL,L指向尾结点,将其释放L=NULL; //free函数只是将之前动态分配给L的内存归还给系统,但是指针类型的结点L仍然存在//为了防止之后发生野指针访问,将L赋值为NULL printf("线性表已销毁\n"); } //对线性表进行重置StatusClearList_L(LinkList&L) { if(!L->next){ printf("线性表为空表,不需要重置\n"); returnERROR; } LinkListp,q; p=L->next; //将单链表的头结点赋值给pwhile(p){ q=p->next; //将单链表的首元结点赋值给qfree(p); p=q; } L->next=NULL; //将头结点的指针域赋值为空 printf("线性表已重置\n"); returnOK; } //判断线性表是否为空StatusListEmpty_L(LinkListL) { if(L){ if(L->next==NULL) //如果首元结点不存在 printf("线性表是空表\n"); elseprintf("线性表不是空表\n"); } else{ printf("线性表不存在,无法判断\n"); } returnOK; } //获取线性表的长度StatusListLength_L(LinkListL,intcount) { //L为带头结点的单链表的头指针,count为计数器LinkListp=L->next; //定义p为单链表L的指针域 while(p){ p=p->next; count++; } returncount; } //获取线性表某一位置对应的元素StatusGetElem_L(LinkListL,intindex) { LinkListp; p=L->next; //使p指向L的首元结点intcount=1; //count为计数器 ,赋值等于1的原因是从首元结点开始计数 while(p&&count<index){ //顺着指针向后查找,直到p指向第index个元素或p为空 p=p->next; count++; //此时p一直指向第count个元素 } if(!p||count>index){ printf("当前位置没有元素\n"); returnERROR; } printf("第%d个元素的值是:%d\n",index,p->data); returnOK; } //在线性表某一位置插入元素StatusListInsert_L(LinkList&L,intindex,ElemTypee) { LinkListp,q; p=L; //将线性表的头结点赋值给pintcount=0; //count为计数器 while(p&&count<index-1){ //寻找第index-1个结点 p=p->next; //此时的p结点指向第index-1个结点 count++; } if(!p||count>index-1){ //越界判断,index小于1或是index大于表长加1 printf("当前结点无法插入元素\n"); returnERROR; } q= (LinkList)malloc(sizeof(LNode)); q->data=e; //将e赋值到q的数据域当中q->next=p->next; p->next=q; printf("元素插入成功\n"); returnOK; } //删除线性表某一位置的元素StatusDeleteList_L(LinkList&L,intindex) { LinkListp,q; p=L; //将线性表的头结点赋值给pintcount=0; //计数器while(p->next&&count<index-1){ p=p->next; count++; //此时p一直指向第count个结点 } if(!(p->next) ||count>index-1){ //越界判断 printf("当前位置无法删除元素\n"); returnERROR; } q=p->next; p->next=q->next; free(q); q=NULL; printf("当前位置元素已删除\n"); returnOK; } //求线性表某一元素的前驱 StatusPriorElem_L(LinkListL,intindex) { LinkListp; intcount=0; //count为计数器 p=L; while(p->next&&count<index-1){ //寻找第index-1个结点 p=p->next; //p一直指向第count个结点 count++; } if(!(p->next) ||count>index-1){ //越界判断 printf("当前位置无法求该元素的前驱\n"); returnERROR; } if(p!=L) //如果要获取第一个元素的前驱,就是获取头结点数据域的值 printf("该元素的前驱为:%d\n",p->data); elseprintf("该位置的前驱是头结点\n头结点的数据域中存储的值为:%d\n",p->data); returnOK; } //求线性表某一元素的后继 StatusNextElem_L(LinkListL,intindex) { LinkListp; intcount=0; p=L->next; while(p&&count<index){ //不断遍历寻找第index之后的结点 p=p->next; //p一直指向index-1的后一个结点 count++; } //!p的目的是为了确保i不大于表长-1,count>index的目的是为了确保index不小于0 if(!p||count>index){ //越界判断printf("当前位置无法求该元素的后继\n"); returnERROR; } printf("该元素的后继为:%d\n",p->data); } //打印线性表StatusPrintList_L(LinkListL) { if(!L){ //如果线性表不存在,返回ERROR printf("线性表不存在,无法打印\n"); returnERROR; } LinkListp; p=L->next; //将L的首元结点赋值给p ,为了不将头结点打印出来 while(p){ printf(" %d",p->data); //将p结点的数据域输出 p=p->next; //结点不断的向后移动 } printf("\n"); returnOK; } intmain(){ SetConsoleTitle("Dream_飞翔"); //控制windows终端控制台的名称 //system("mode con cols=60 lines=30"); 这条语句可以控制windows终端控制台的大小 LinkListL=NULL; //声明线性表的头结点,但是并未进行初始化 intchoose,index,e,Num,Value,k; while(1){ printf("*****************************************\n"); printf("* *\n"); printf("* 线性表的链式表示和实现: *\n"); printf("* *\n"); printf("* 1. 构造一个空的头结点 *\n"); printf("* 2. 对线性表进行赋值 *\n"); printf("* 3. 对线性表进行销毁 *\n"); printf("* 4. 对线性表进行重置 *\n"); printf("* 5. 判断线性表是否为空 *\n"); printf("* 6. 获取线性表的长度 *\n"); printf("* 7. 获取线性表某一位置对应的元素 *\n"); printf("* 8. 在线性表某一位置插入元素 *\n"); printf("* 9. 删除线性表某一位置的元素 *\n"); printf("* 10. 求线性表某一元素的前驱 *\n"); printf("* 11. 求线性表某一元素的后继 *\n"); printf("* 12. 打印线性表 *\n"); printf("* 13. 退出 *\n"); printf("* *\n"); printf("*****************************************\n"); printf("请做出您的选择:"); scanf("%d",&choose); switch(choose){ case1:InitList_L(L);break; case2:{ if(L){ //对线性表赋值的前提是线性表的头结点存在 printf("请输入线性表元素的个数:"); scanf("%d",&Num); if(Num>0){ for(inti=1;i<=Num;i++){ printf("请输入第%d个元素的值:",i); scanf("%d",&Value); ValueList_L(L,Value); } printf("线性表赋值成功\n"); } elseprintf("请输入一个有效数字\n"); } elseprintf("线性表不存在,无法赋值\n"); } break; case3:DistoryList_L(L);break; case4:ClearList_L(L);break; case5:ListEmpty_L(L);break; case6:{ intcount=ListLength_L(L,1); printf("线性表的长度为:%d\n",count-1); };break; case7:{ printf("请输入要获取元素的位置:"); scanf("%d",&index); GetElem_L(L,index); } break; case8:{ printf("请输入插入元素的位置:"); scanf("%d",&index); printf("请输入插入元素的值:"); scanf("%d",&e); ListInsert_L(L,index,e); } break; case9:{ printf("请输入要删除元素的位置:"); scanf("%d",&index); DeleteList_L(L,index); } break; case10:{ if(L){ printf("请输入想要查找哪一个元素的前驱:"); scanf("%d",&index); PriorElem_L(L,index); } elseprintf("线性表不存在,无法获取其中元素的前驱\n"); } break; case11:{ if(L){ printf("请输入想要查找哪一个元素的后继:"); scanf("%d",&index); NextElem_L(L,index); } elseprintf("线性表不存在,无法获取其中元素的后继\n"); } break; case12:PrintList_L(L);break; case13:exit(0); } } return0; }