链表的创建,遍历,删除,打印,释放操作,C语言

#include <stdio.h>
#include <malloc.h>
struct cell {//单链表结点结构体定义
    int x;
     struct cell* next; };

     struct cell* build(void) {//新建单链表,并将建好的单链表首结点地址返回
          struct cell* head, * tmp, * p;
          head = tmp = p = NULL;
           int n; /*请在以下位置补充完整,实现函数build的功能       ......       ......       ......   */
          while(scanf("%d",&n),n!=0)
          {p=(struct cell*)malloc(sizeof(struct cell));//必须申请空间,不然出错
              p->x=n;
              p->next=NULL;
              if(head==NULL)//如果不把头结点更新,就会导致头结点与后面的元素断裂,出错
              {
                  head=p;
                  tmp=p;
              }
              else{
                tmp->next=p;//尾插法,先把新结点数据写好,next为null,再把尾结点更新,尾结点的ext一定是null;
                tmp=p;
              }
          }
           return head;}

          struct cell* del2one(struct cell* head) {//删除重复结点只保留一个,head是单链表首结点指针
               struct cell*p, * pre,*q;//需要双重循环依次比较所有要两个指针,但是要删除必须知道删除元素的前驱,所有还需要有一个指针q,来记录pre的前驱
               p=head;

               while(p!=NULL)
               { pre=p->next;//从p的下一个元素开始遍历,q在pre前面;
               q=p;
                   while(pre!=NULL)
                   {
                       if(p->x==pre->x)
                       {
                           q->next=pre->next;//删除操作,删除pre后释放pre结点空间,更新pre的位置
                           free(pre);
                           pre=q->next;
                       }else{//如果相同则pre,q都不用再动,因为删除的时候已经更新过了,在更新会导致有元素没有遍历到。只有不同的时候才往下更新
                           if(pre!=NULL){
                         pre=pre->next;//在删除链表最后一个元素的时候,如果在对pre->next进行引用就会导致空指针引用错误
                       q=q->next;
                       }

                       }

                   }
                   p=p->next;
               }
               return head;//返回删除重复结点的单链表头
                }
         void print(struct cell* head) {//打印整个单链表,head是单链表首结点指针
              struct cell*p;
            p=head;
            while(p!=NULL)
            {if(p->next==NULL)
           {
               printf("%d",p->x);
               p=p->next;//老是忘记这个,如果没有这条语句就会无限循环,因为p不会==NULL;
           }
            else
               {printf("%d ",p->x);
                p=p->next;
            }

               }
               }
             void release(struct cell* head) {//释放单链表空间,head是单链表首结点指针
                 struct cell*p,*a;
                 p=head;
                 while(p!=NULL)
                 {
                     a=p->next;
                     free(p);
                     p=a;
                 }
                 }
                int main(void) {
                          struct cell* head;
                      head = build();
                      head=del2one(head);
                       if(head!=NULL)
                            print(head);
                          else
                            printf("NULL");
                             release(head);
                             return 0; }

写在注释里了,直接看代码,这是我自己犯过的错误,所以记着

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值