作业:
单链表的基操+双链表的基操
感受:
做梦梦到链表跟我说:“系兄弟就起身打我。”
问题:
- 搞不明白指针的指针,申请内存时候花了很多时间。->加上*当初一级指针使用。
- 多文件路径问题,头文件main中引用就可以了。
- 不会丢弃数据,一下子输入很多数据就疯狂输出。
- 项目结构要优化。
收获:
- 认识了双向链表。
- 双向链表的销毁要把前指针也指向NULL,不然会因为指向已释放内存报错。
- 遍历不能动头指针。
- 做完自定义插入感觉自己牛逼坏了。
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "linkedList.h"
Status InitList(LinkedList *L) {
//初始化链表
*L=(LinkedList)malloc(sizeof(LNode));
if(*L==NULL)return 0;
else {
(*L)->next=NULL;
printf("请输入一个整型数据:\n");
while(!(scanf("%d",&((*L)->data)))){
printf("请输入正确的数据类型!\n");
setbuf(stdin, NULL);
}
return 1;
}
}
void DestroyList(LinkedList *L){ //销毁链表
LinkedList p = *L;
while((*L)->next){
p=(*L)->next;
free(*L);
*L=p;
}
free(*L);
*L = NULL;
printf("销毁完成\n");
}
Status InsertList(LNode *p, LNode *q) {
//在节点p之后插入节点q
LNode *r;
if(p==NULL){
return 0;
}else{
if(p->next==NULL){
p->next=q;
q->next=NULL;
}else{
r=p->next;
p->next=q;
q->next=r;
}
return 1;
}
}
Status DeleteList(LNode *p, ElemType *e) {
//删除节点p后的第一个节点,并将其值赋给e
if(p==NULL||p->next==NULL)return 0;
else{
if(p->next->next==NULL){
e=&(p->next)->data;
p->next=NULL;
}else{
e=&(p->next)->data;
p->next=p->next->next;
}
return 1;
}
}
void TraverseList(LinkedList L, void (*visit)(ElemType e)) {
//遍历
LinkedList p;
for(p=L;p->next!=NULL;p=p->next)printf("%d ",p->data);
printf("%d\n",p->data);
}
Status SearchList(LinkedList L, ElemType e) {
//根据e找到链表中的第一个节点
LinkedList p;
ElemType i=0,f=0;
if(L->data==e){
i=1;
f=1;
return i;
}
else{
for(p=L;p!=NULL;i++){
if(p->data==e){
f=1;
break;
}
if(p->next==NULL)break;
p=p->next;
}
if(f)return i+1;
else return 0;
}
}
Status ReverseList(LinkedList *L) {
//反转
LinkedList p=NULL,q=NULL,r=NULL;
int i=1;
if((*L)->next==NULL)i=0;
else if((*L)->next->next==NULL){
p=(*L)->next;
(*L)->next=NULL;
p->next=(*L);
*L=p;
for(;(*L)->next!=NULL;*L=(*L)->next){
printf("%d ",(*L)->data);
}
printf("%d\n",(*L)->data);
*L=p;
}else{
p=*L;
q=(*L)->next;
r=(*L)->next->next;
p->next=NULL;
while(1){
q->next=p;
p=q;
q=r;
if(q->next==NULL){
r->next=p;
break;
}
r=r->next;
}
for(*L=r;r->next!=NULL;r=r->next)printf("%d ",r->data);
printf("%d\n",r->data);
}
return i;
}
Status IsLoopList(LinkedList L) {
//判断是否循环
LinkedList q=NULL,p=NULL;
int i=0;
q=p=L;
while(q->next!=NULL&&q->next->next!=NULL){
p=p->next;
q=q->next->next;
if(p==q){
i=1;
break;
}
}
return i;
}
LNode* FindMidNode(LinkedList *L) {
LinkedList p=NULL,q=NULL;
p=q=*L;
if(p->next==NULL||p->next->next==NULL){
printf("%d \n",p->data);
return p;
}else{
while(q->next!=NULL&&q->next->next!=NULL){
p=p->next;
q=q->next->next;
}
printf("%d \n",p->data);
return p;
}
}
Status add(LinkedList *L){
LinkedList q=NULL,p=NULL;
ElemType a = 0;
while(!(scanf("%d",&a))){
printf("请输入正确的数据类型!\n");
setbuf(stdin, NULL);
}
if((*L)->next==NULL){
p=(LinkedList)malloc(sizeof(LNode));
(*L)->next=p;
p->data=a;
}else{
for(q=*L;q->next!=NULL;q=q->next)continue;
p=(LinkedList)malloc(sizeof(LNode));
q->next=p;
p->data=a;
}
p->next=NULL;
return 1;
}
int main(int argc, const char * argv[])
{
LinkedList L=NULL,L0=NULL,newNode=NULL,insert=NULL,del=NULL;
ElemType delete=0;
ElemType c=0,search=0,searched=0;
void (*visit)(ElemType e) = NULL;
int cho=0,f=0;
do{
printf("*****************请选择********************\n");
printf("**************1.构造链表*******************\n");
printf("**************2.结束程序*******************\n");
setbuf(stdin, NULL);
scanf("%d",&cho);
switch(cho){
case 1:
if(InitList(&L)){
printf("构造完成\n");
f=0;
}
else {
printf("构造失败\n");
f=1;
}
break;
case 2:exit(1);break;
default:
printf("请输入正确的指令!\n");
f=1;
}
}while(f);
do{
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("**************0.结束程序*******************\n");
setbuf(stdin, NULL);
scanf("%d",&cho);
switch(cho){
case 1:DestroyList(&L);break;
case 2:
printf("请输入想要查找的节点数据:\n");
scanf("%d",&search);
searched=SearchList(L, search);
while(!searched){
printf("未找到该节点,请重新输入:\n");
setbuf(stdin, NULL);
scanf("%d",&search);
searched=SearchList(L, search);
}
setbuf(stdin, NULL);
printf("已找到该节点,请输入想插入的数据:\n");
newNode=(LinkedList)malloc(sizeof(LNode));
if(newNode==NULL){
printf("申请内存失败\n");
exit(-1);
}
while(!(scanf("%d",&(newNode->data)))){
printf("请输入正确的数据类型!\n");
setbuf(stdin, NULL);
}
insert=L;
for(ElemType i=1;i<searched;i++){
insert=insert->next;
}
if(InsertList(insert,newNode))printf("插入成功\n");
else printf("插入失败\n");
break;
case 3:
printf("请输入想要查找的节点数据:\n");
scanf("%d",&delete);
searched=SearchList(L, delete);
while(!searched){
printf("未找到该节点,请重新输入:\n");
setbuf(stdin, NULL);
scanf("%d",&delete);
searched=SearchList(L,delete);
}
setbuf(stdin, NULL);
printf("已找到该节点 位于第%d位\n",searched);
del=L;
for(ElemType i=1;i<searched;i++){
del=del->next;
}
if(DeleteList(del,&delete)) printf("删除成功\n");
else printf("该节点不可删除\n");
break;
case 4:TraverseList(L,(*visit));break;
case 5:
printf("请输入要查询的数据:\n");
scanf("%d",&c);
if(SearchList(L,c))printf("已找到 在第%d个节点\n",SearchList(L,c));
else printf("未找到\n");
break;
case 6:
if(ReverseList(&L))printf("反转完成\n");
else printf("该链表不可反转\n");
break;
case 7:
if(IsLoopList(L))printf("存在成环\n");
else printf("没有成环\n");
break;
case 8:L0=FindMidNode(&L);break;
case 9:
printf("请输入一个整型数据:\n");
if(add(&L))printf("添加成功!\n");
break;
case 0:exit(1);
default:printf("请输入正确的指令!\n");
}
}while(L!=NULL);
return 0;
}