链表的各种操作
链表的操作包括插入、删除、翻转、清空、判空、求链表长度等,下面分别找了链表的插入和删除操作的图,第一个是插入,第二个是删除。
在插入的时候,要先找到待插入的位置,一般是找到待插入位置的前一个位置,假如要在3号位置插入,那就找到2号位置,这样方便插入,下面
的代码中就提到了这一点,然后把新结点插入在3号位置就行了;有没有发现在链表中插入某一结点和用头插法创建链表有点像 !
在删除的时候,还是要先找到要删除的位置,基本上和插入操作一样,也是找到待删除位置的前一个位置,上面图中要删除A3,就找到A2,改变
A2的next,跳过A3直接指向A4,这样链表中就没了A3。
关于链表的具体用法,还是看下面代码吧,代码我写的超详细,也测试过了,基本上包括了链表的各种操作,耐心点看吧!如有不对的地方,欢迎指出!
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define N 10 //结点个数 4 typedef struct LNode 5 { 6 int data; 7 struct LNode *next; 8 }LNode,*LinkList; 9 10 LinkList creat_Linklist() //已知节点个数,并且不带头结点 11 { 12 LNode *head=NULL,*s,*rear=NULL; //尾插法需要用到尾指针,rear是尾指针 13 for(int i=1;i<=N;i++) 14 { 15 s=(LinkList)malloc(sizeof( LNode)); 16 scanf("%d",&s->data); 17 s->next=NULL; //把当前结点next置空NULL 18 if(i==1) //用来标记插入的节点是否为第一个节点,是的话就让头结点head指向第一个节点 19 head=s; 20 else 21 rear->next=s; //不是头结点的话就让上一个节点的next指向当前结点 22 rear=s; //尾指针rear指向当前节点 23 } 24 return head; //返回头指针 25 } 26 int LinkList_length(LinkList head) //q求链表长度 27 { 28 29 int count=0; 30 LNode * p=NULL; 31 p=head; 32 while(p!=NULL) 33 { 34 p=p->next; 35 count++; 36 } 37 return count; 38 } 39 LinkList Clear_LinkList(LinkList head) //用于清空没有头结点的链表,只是清空,没有释放掉,直接把头指针置空NULL即可 40 { 41 if(head==NULL) 42 { 43 printf("链表为空\n "); 44 exit(-1); 45 } 46 return NULL; 47 } 48 int EmptyList(LinkList head)//用于判断没有头结点的情况;空表返回1,非空返回0 49 { 50 if(head==NULL) 51 return 1; 52 else 53 return 0; 54 } 55 LinkList Search(LinkList head,int x) //查找链表中的某一数据,查找成功返回一个指向它的指针,失败返回NULL 56 { 57 LNode *p; 58 p=head; 59 while(p) 60 { 61 if(p->data!= x) 62 p=p->next; 63 else 64 break; 65 } 66 return p; 67 } 68 void Print_LinkList(LinkList head) //打印链表 69 { 70 LNode *p; 71 p=head; 72 while(p!= NULL) 73 { 74 printf("%d ",p->data); 75 p=p->next; 76 } 77 } 78 LinkList reverseList(LinkList head) //翻转链表 79 { 80 LNode *pre,*cur,*net; 81 pre=head; 82 cur=pre->next; 83 while(cur!= NULL) //当前指针cur非空 84 { 85 net=cur->next; 86 cur->next=pre; 87 pre=cur; 88 cur=net; 89 } 90 head->next=NULL; //将原来链表中第一个结点的next置空NULL 91 head=pre; //此时pre指向最后一个结点 92 return head; 93 } 94 LinkList DeleteList(LinkList head,int i) //删除序号为i的结点,结点序号从1开始 95 { 96 int j=1; 97 LNode *p,*q; 98 p=head; 99 while(p->next!=NULL&&j<i-1) 100 { 101 p=p->next; 102 j++; //查找待删除结点的前一个节点 103 } 104 if ( !(p->next) || j>i-1) //1号位置无法删除 105 { 106 printf("删除位置错误"); 107 return 0; 108 } 109 q=p->next; //q指向待删除结点 110 p->next=q->next; //跳过待删除结点, 111 free(q); //释放待删除结点 112 return head; 113 } 114 LinkList InsertList(LinkList head,int i,int e)//在序号为i的结点位置插入e 115 { 116 int j=1; 117 LNode *p,*q; 118 p=head; 119 while(p&&j<i-1) //查找待插入位置的前一个位置 120 { 121 p=p->next; 122 j++; 123 } 124 if(!p || j>i-1) //1号位置无法插入 125 { 126 printf("插入位置错误"); 127 return 0; 128 } 129 q=(LinkList)malloc(sizeof(LNode)); //为新结点开辟空间 130 q->data=e; 131 q->next=p->next; 132 p->next=q; 133 return head; 134 } 135 int main() 136 { 137 LinkList p; 138 p=creat_Linklist(); 139 printf("链表中的数据为:"); 140 Print_LinkList (p); 141 printf("\n链表长度:%d\n",LinkList_length(p)); 142 printf("翻转后的链表为:"); 143 p=reverseList (p); //翻转链表,返回头指针 144 Print_LinkList (p); 145 printf("\n删除序号为3的结点后,链表中的元素为:"); 146 p=DeleteList(p,3); //删除序号为3的结点,序号从1开始 147 Print_LinkList(p); 148 printf("\n删除序号为3的结点后,链表长度:%d",LinkList_length(p)); 149 printf("\n在序号为3的结点位置插入80后,链表中的元素为:"); 150 p=InsertList(p,3,80); 151 Print_LinkList(p); 152 printf("\n在序号为3的结点位置插入80后,链表长度为:%d\n",LinkList_length(p)); 153 LinkList s; 154 s=Search(p,80);//在链表里查找某一数据 155 if(s==NULL) 156 printf("在链表查找失败\n"); 157 else 158 printf("在链表查找成功,结果为:%d\n",*s); 159 printf("结果为1表示链表为空,为0表示链表非空:%d\n",EmptyList(p)); 160 p=Clear_LinkList(p); //清空链表 161 printf("结果为1表示链表为空,为0表示链表非空:%d\n",EmptyList(p)); 162 printf("清空链表后,链表长度为:%d\n",LinkList_length(p)); 163 return 0; 164}
调试了好久,结果如下:
另外链表的销毁操作我没测试,附上代码,有兴趣的自己去测试吧
1 void Destroy_LinkList (LinkList head) 2 { 3 LNode *p,*q; 4 p=head; 5 while(p != NULL) 6 { q=p; 7 p=p->next; 8 free(q); 9 } 10 }
转载请注明出处 !
2020-04-28 23:07:21