您的位置:首页 > 编程语言 > C语言/C++

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

2015-10-01 16:09 976 查看
//

//  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)

int n;                        
//外部变量n,用于创建链表时记录元素数量
int L1,L2;                    
//记录各个链表的元素数量

struct Student                
//利用结构体创建一个链表元素
{
   
int num;
   
float score;
   
struct Student * next;
};

struct Student * creat2()      
//链表建立函数,此函数将会返回一个链表头地址
{

    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);                               
//返回链表头地址
}

void print(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 del(struct
Student *head,int L)                 
//链表删除函数
{
   
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);                  
//释放被删除的链表元素内存
    L=L-1;                    
//计数器减一
   
print(head);

    
}

void insert(struct
Student *head,int L)    
//链表插入函数,思路与删除函数类似
{
   
int insertnum;                   
//在指定的链表元素后加入一个新元素
   
struct Student *p,*temp,*new;

    printf("\nAfter which point 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);  
//新元素成员赋值
    L=L+1;
   
print(head);
}

void combine(struct
Student *heada,struct
Student *headb,int L1,int L2)  
//链表合并并重新排列顺序函数
{

    

    struct
Student *p[L1+L2];    
//建立一个指针数组记录两个链表的各个元素地址

    
    p[0]=heada;

    
   
for(int i=0;i<L1;i++)       
//遍历并复制第一个链表的各元素地址
    {
        p[i+1]=p[i]->next;
    }

    
    p[L1]=headb;

    
   
for(int i=0;i<L2;i++)       
//遍历并复制第二个链表的各元素地址
    {
        p[L1+i+1]=p[L1+i]->next;
    }

    
    p[L1+L2-1]->next=p[L1+L2]=NULL;

    
   
struct Student *temp;
    temp=malloc(LEN);
   
for(int i=0;i<L1+L2;i++)            
//指针数组重新排序
    {
       
for(int j=i+1;j<L1+L2;j++)
        {
           
if(p[i]->num>p[j]->num)    
//根据num大小进行重新排序
            {
                temp=p[j];p[j]=p[i];p[i]=temp;
            }
        }
    }

    
   
for(int i=0;i<(L1+L2);i++)        
//将重新排序好的链表各元素进行链接
    {
        p[i]->next=p[i+1];
    }
    p[L1+L2-1]->next=p[L1+L2]=NULL;

    
   
for(int i=0;i<(L1+L2);i++)        
//输出
    {
       
printf("%5.2d,%5.2f\n",p[i]->num,p[i]->score);
        p[i]=p[i]->next;
    }
}

void del2(struct
Student *heada,struct
Student*headb,int L1,int L2)  
//如果第一个链表的num与第二个链表重复,则删除第一个链表的此
{                                                                    
//元素
   
int flag=0;
   
struct Student *p1[L1+1];
   
struct Student *p2[L2+1];

    
    p1[0]=heada;

    
   
for(int i=0;i<L1;i++)
    {
        p1[i+1]=p1[i]->next;     
//遍历复制第一个链表各元素
    }

    
    p2[0]=headb;

    
   
for(int i=0;i<L2;i++)
    {
        p2[i+1]=p2[i]->next;    
//遍历复制第二个链表各元素
    }

    
    p1[L1-1]->next=NULL;
    p1[L1]=NULL;
    p2[L2-1]->next=NULL;
    p2[L2]=NULL;

    
   
int temp=-99;               
//temp记录被删除的元素的序号
   
int temp2=0;                
//temp2用来处理出现连续重复的情况
   
for(int i=0;i<L2;i++)       
//遍历第二个链表各元素
    {
       
for(int j=0;j<L1;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;                  
//特殊情况关闭
        }
    }

    
   
while(p1[0]!=0)                  
//输出
    {
       
printf("%5.2d,%5.2f\n",p1[0]->num,p1[0]->score);
        p1[0]=p1[0]->next;
    }
}

void del3(struct
Student *heada,int L)    
//根据指定条件删除链表元素
{
   
int flag;
   
int delete;
   
struct Student *p,*temp;
    p=heada;

    printf("\nWhich num you want to delete?\n");
   
scanf("%d",&delete);

    
   
for(int i;p->num;i++)       
//先处理一种特殊情况,既第一个链表元素要被删除
    {
       
if(p->num!=delete)
        {
           
break;
        }

        
       
else
        {
            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永远记录最后一个未被删除的元素
        }
    }
   print(heada);
}

int main()
{
   
struct Student * creat2(void);         
//各函数声明
   
void print(struct
Student *);
   
void del(struct
Student *,int);
   
void insert(struct
Student *,int);
   
void combine(struct
Student *,struct
Student *,int,int);

    void del2(struct
Student *,struct
Student*,int,int);
   
void del3(struct
Student*,int);

    
   
struct Student *heada,*headb;
    heada=creat2();          
//生成一个链表
   
L1=n;
    headb=creat2();         
//生成第二个链表
   
L2=n;

    
   
int choice;

    

    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");
   
scanf("%d",&choice);
   
switch(choice)
    {
       
case 1:print(heada);break;           
//调用各函数
       
case 2:del(heada,L1);break;
       
case 3:insert(heada,L1);break;
       
case 4:combine(heada,headb,L1,L2);break;
       
case 5:del2(heada,headb,L1,L2);break;
       
case 6:del3(heada,L1);break;
    }
   
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息