C语言单向动态链表程序,实现链表的建立,合并,重新排序,链表元素的插入与删除,以及根据元素成员的值进行元素删除。

  LinkedList.c
  C exercise
  Created by y liu on 15/10/1.
  Copyright © 2015年 y liu. All rights reserved.


//库&全局/
  #include <stdio.h>
  #include <stdlib.h>
  #include <math.h>

  #define LEN sizeof(struct Student)
  struct Student                 //利用结构体创建一个链表元素,此元素记录一个学生的学号和成绩
  {    
    int num;    
    float score;    
    struct Student * next;
  };
//链表建立函数,此函数将会返回一个链表头地址/
  struct Student * CreatLinkedList()      
  {    
    printf("Creat a LinkedList.Enter 0 to end the process\n");    
    struct Student *head;                 //链表头
    struct Student *p1,*p2;               //建立一个链表,我们需要两个指针进行各节点的链接    
    n=0;    
    p1=p2=(struct Student *)malloc(LEN);  //开辟了第一个链表元素的空间    
    scanf("%d,%f",&p1->num,&p1->score);   //给第一个链表元素的成员赋值    
    head=NULL;    
    while(p1->num!=0)                          //如在给链表元素第一个成员赋值时输入0并回车则结束函数    
    {        
      n=n+1;                                   //链表节点计数        
      if(n==1)
      {
        head=p1;                //head指针获取链表头地址 
      }                                 
      else 
      {
        p2->next=p1;            //最后一个链表元素的尾部指针连接新开辟的链表元素的地址
      }                                
      p2=p1;                                    //p2指向下一个链表元素,准备下一个节点的链接        
      p1=(struct Student*)malloc(LEN);          //p1指针脱离链表开辟新空间        
      scanf("%d,%f",&p1->num,&p1->score);       //给每个链表元素的成员赋值    
    }    
    p2->next=NULL;                              //最后一个链表元素的指针指向空值    
    return head;                               //返回链表头地址
  }
//获取链表长度函数/
int GetLLLength(struct Student *head)
{
  struct Student *p;
  p=head;
  int counter=0;
    
  while(p!=NULL);        
  {            
    p=p->next;                             
    counter+=1;        
  }

  return counter;
}
//链表输出函数/
  void PrintLinkedList(struct Student *head)    
  {    
    struct Student *p;    
    printf("\nNow,These records are:\n");    
    p=head;    
    if(head!=NULL)    
    {        
      do        
      {            
        printf("%d%5.1f\n",p->num,p->score);            
        p=p->next;                              //p不断寻找下一个链表元素        
      }
      while(p!=NULL);    
    }
  }
//链表删除函数/
  void RemoveByPos(struct Student *head)
  {    
    int delete;                                 //将要删除的链表元素    
    struct Student *p,*temp;                    //指针p用于遍历链表元素,temp用于链接被删除元素的前后两个元素    
    printf("\nWhich member of LinkedList you want to delete?\n");    
    scanf("%d",&delete);    
    p=head;    
    temp=head;    
    for(int i=1;i<delete;i++)           //假如我们要删除第五个链表元素,temp必须指向第四个元素,p指向第五个元素,    
    {                                   //这样,p的尾部指针就等于第六个元素的地址,4与6可以链接        
      if(i==(delete-1))        
      {            
        temp=p;                //temp指向被删除元素的前一个元素        
      }        
      p=p->next;               //p指向即将被删除的元素    
    }        
    temp->next=p->next;        // 被删除元素的前一个元素的尾部指针指向被删除元素的下一个元素,被删除元素脱离链表    
    free(p);                   //释放被删除的链表元素内存    
    PrintLinkedList(head);    
  }
//链表插入函数,思路与删除函数类似/
  void Insert(struct Student *head)
  {    
    int insertNum;                      //在指定的链表元素后加入一个新元素    
    struct Student *p,*temp,*new;    
    printf("\nWhere you want to insert?\n");    
    scanf("%d",&insertNum);    
    p=head;    
    temp=head;    
    for(int i=1;i<=insertNum;i++)   //假如我们要在第五个链表元素后插入,temp必须指向第五个元素,p指向第六个元素,    
    {        
      if(i==(insertNum))        
      {            
        temp=p;                     //temp指向将要插入元素的前一个元素        
      }        
      p=p->next;                    //p指向将要插入元素的后一个元素    
    }    
    new=malloc(LEN);                //为即将插入的元素开辟内存,new既是将要插入的元素    
    temp->next=new;                 //插入元素的前一个元素的尾部指针指向插入的元素    
    new->next=p;                    //插入元素指针指向后一个元素    
    printf("\nPlease enter the number and the score.\n");    
    scanf("%d,%f",&new->num,&new->score);   //新元素成员赋值    
    PrintLinkedList(head);
  }
//链表合并并重新排列顺序函数/
  struct Student * LinkAndSort(struct Student *headA,struct Student *headB)
  {        
    int lengthA=GetLLLength(*headA);
    int lengthB=GetLLLength(*headB);
    int lengthAll=lengthA+lengthB;
    struct Student *p[lengthA+lengthB];     //建立一个指针数组记录两个链表的各个元素地址        
    p[0]=headA;        
    for(int i=0;i<lengthA;i++)              //遍历并复制第一个链表的各元素地址    
    {        
      p[i+1]=p[i]->next;    
    }        
    p[lengthA]=headB;        
    for(int i=0;i<lengthB;i++)              //遍历并复制第二个链表的各元素地址    
    {        
      p[lengthA+i+1]=p[lengthA+i]->next;    
    }        
    p[lengthAll-1]->next=p[lengthAll]=NULL;        
    struct Student *temp;    
    temp=malloc(LEN);    
    for(int i=0;i<lengthAll;i++)             //指针数组重新排序    
    {        
      for(int j=i+1;j<lengthAll;j++)        
      {            
        if(p[i]->num>p[j]->num)          //根据num大小进行重新排序            
        {                
          temp=p[j];
          p[j]=p[i];
          p[i]=temp;            
        }        
      }    
    }        
    for(int i=0;i<(lengthAll);i++)         //将重新排序好的链表各元素进行链接    
    {       
      p[i]->next=p[i+1];    
    }    
    p[lengthAll-1]->next=p[lengthAll]=NULL;  

    PrintLinkedList(p[0])
    return p[0];
  }
//如果第一个链表的num与第二个链表重复,则删除第一个链表的此元素/
  void Combine(struct Student *headA,struct Student*headB)
  {                                                                        
    int lengthA=GetLLLength(*headA);
    int lengthB=GetLLLength(*headB);
    int lengthAll=lengthA+lengthB; 
    int flag=0;    
    struct Student *p1[lengthA+1];    
    struct Student *p2[lengthB+1];        
    p1[0]=headA;        
    for(int i=0;i<lengthA;i++)    
    {        
      p1[i+1]=p1[i]->next;      //遍历复制第一个链表各元素    
    }        
    p2[0]=headB;        
    for(int i=0;i<L2;i++)    
    {        
      p2[i+1]=p2[i]->next;     //遍历复制第二个链表各元素    
    }        
    p1[lengthA-1]->next=NULL;    
    p1[lengthA]=NULL;    
    p2[lengthB-1]->next=NULL;   
    p2[lengthB]=NULL;        
    int temp=-99;                //temp记录被删除的元素的序号    
    int temp2=0;                 //temp2用来处理出现连续重复的情况    
    for(int i=0;i<lengthB;i++)        //遍历第二个链表各元素    
    {        
      for(int j=0;j<lengthA;j++)    //遍历第一个链表各元素        
      {                        
        if(p2[i]->num==p1[j]->num)   //如果发现num重复,将分以下4种情况区别处理            
        {                
          if(j==temp+1)                      //3,如果出现连续重复,temp2+1,为了一直返回操作最后一个未重复元素的尾部指针指向下一                
          {                                  //元素地址                    
            temp2++;                
          }                
          if(j!=temp+1)           //如果无连续重复情况,temp2归0                
          {                    
            temp2=0;                
          }                
          if(j==0||flag)                         //1,如果是第一个链表的第一个元素,链表头指向第二个元素并直接开始第二次循环                
          {                    
            p1[j]=p1[j]->next;                    
            flag=1;                              //4,特殊情况,从第一个元素开始出现连续重复,开启开关,当前元素尾部指针直接                    
            continue;                            //指向下一个元素,并直接开始下一次循环                
          }                
          p1[j-1-temp2]->next=p1[j+1];           //2,当前元素前一个元素的尾部指针指向当前元素的后一个元素的地址,当前元素脱离链表                
          temp=j;                                //temp记录被删除元素序号            
        }            
        flag=0;                                  //特殊情况关闭        
      }    
    }        
    PrintLinkedList(headA);
    PrintLinkedList(headB);
  }
//根据指定条件删除链表元素/
  void RemoveByNum(struct Student *headA)     
  {    
    int flag;    
    int delete;   
    struct Student *p,*temp;    
    p=headA;    
    printf("\nWhich num you want to delete?\n");    
    scanf("%d",&delete);        

    if(p->num==delete){   //先处理一种特殊情况,既第一个链表元素要被删除   
      p=p->next;          //如出现此情况,链表头直接指向下一个元素     
    }

    headA=temp=p;                 //temp指向当前第一个元素    
    for(int i;p->next;i++)    
    {        
      flag=0;                //flag记录需要连续删除的情况        
      p=p->next;             //遍历链表各元素        
      if(p->num==delete)    //如果发现元素符合指定删除条件,前一个元素尾部指针指向下一个元素地址,连续删除开关打开        
      {            
        flag=1;            
        temp->next=p->next;        
      }        
      if(!flag)        
      {        
        temp=p;          //temp永远记录最后一个未被删除的元素        
      }    
    }   
    PrintLinkedList(headA);
  }
//入口/
  int main()
  {    
    struct Student * CreatLinkedList(void);          //各函数声明    
    void PrintLinkedList(struct Student *);    
    void RemoveByPos(struct Student *,int);    
    void Insert(struct Student *,int);    
    struct Student * LinkAndSort(struct Student *,struct Student *,int,int);    
    void Combine(struct Student *,struct Student*,int,int);    
    void RemoveByNum(struct Student*,int);   
    //测试     
    struct Student *headA,*headB;    
    headA=CreatLinkedList();                         //生成一个链表    
    headB=CreatLinkedList();                         //生成第二个链表    

    printf("What do you want?\n1:print the LinkedList\n2:delete a member of the LinkedList a\n3:insert a member to the LinkedList a\n4:comine the two LinkedLists and reform them according to 'num'\n5:delete the members of LinkedList a if that are same as those of LinkedList b\n6:delete the members of LinkedList a with the certain 'num'\n");    
    int choice;
    scanf("%d",&choice);    
    switch(choice)    
    {        
      case 1:PrintLinkedList(headA);
      break;                   
      case 2:RemoveByPos(headA);
      break;        
      case 3:Insert(headA);
      break;        
      case 4:LinkAndSort(headA,headB);
      break;        
      case 5:Combine(headA,headB);
      break;        
      case 6:RemoveByNum(headA);
      break;    
    }    
    return 0;
  }

=======================================================

维护日志:

2018-7-25:review

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值