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