题目:先创建一个链表(链表中各结点未按学号由小到大排序),然后调用sort函数,将链表中各结点按学号由小到大排序。
法一(超时)
这个题我一开始的思路是利用冒泡的思想,当当前结点比next结点大的时候,交换两者next所指向内容。
比如链表1-5-4-6 , 当指针p指向5所在结点的时候,发现p->next的num小于当前的num,这时候我要令p1=p->next(4所在结点), 让(5)p->next指向 (6)p1->next, 再让 (4)p1->next指向(5)p,最后再让(1)pre接上(4)p1,这样,链表的结点顺序就变成了 1-4-5-6。(注意如果是第一位的话就不用使用pre指针)
#include "stdio.h"
#include "malloc.h"
#define LEN sizeof(struct student)
struct student
{
long num;
int score;
struct student *next;
};
struct student *create(int n)
{
struct student *head=NULL,*p1=NULL,*p2=NULL;
int i;
for(i=1;i<=n;i++)
{ p1=(struct student *)malloc(LEN);
scanf("%ld",&p1->num);
scanf("%d",&p1->score);
p1->next=NULL;
if(i==1) head=p1;
else p2->next=p1;
p2=p1;
}
return(head);
}
void print(struct student *head)
{
struct student *p;
p=head;
while(p!=NULL)
{
printf("%8ld%8d",p->num,p->score);
p=p->next;
printf("\n");
}
}
struct student *insert(struct student *head, struct student *stud)
{ struct student *p0,*p1,*p2;
p1=head; p0=stud;
if(head==NULL)
{head=p0;}
else
{ while( (p0->num > p1->num) && (p1->next!=NULL) )
{ p2=p1; p1=p1->next;}
if( p0->num < p1->num )
{ if( head==p1 ) head=p0;
else p2->next=p0;
p0->next=p1; }
else { p1->next=p0;}
}
return(head);
}
struct student *del(struct student *head,long num)
{
struct student *p1,*p2;
p1=head;
while(p1!=NULL)
{
if(p1->num == num)
{
if(p1 == head) head=p1->next;
else p2->next=p1->next;
free(p1);
break;
}
p2=p1;
p1=p1->next;
}
return(head);
}
struct student *sort(struct student *head)
{
struct student *p1,*p2, *p3,*pre;
int i,j;
p1=head;
int count=0;
while(p1)
{
count++;
p1=p1->next;
}
// printf("%d\n",count);
for(i=1;i<=count;i++)
{
p1=head;
pre=p1;
int count1=0;
while(p1->next!=NULL)
{
count1++;
if(count1<=i) continue;
p2=p1->next;
if(p1->num>p2->num)
{
if(p1==head)
{
p3=p2->next;
p1->next=p3;
p2->next=p1;
pre=p2;
}
else
{
p3=p2->next;
p1->next=p3;
p2->next=p1;
pre->next=p2;
pre=p1;
}
// print(head);
// printf("%d %d %d\n",p1->num,p2->num,p3->num);
}
else
{
pre=p1;
p1=p1->next;
}
// printf("1\n");
}
}
return head;
}
main()
{
struct student *head,*stu;
int n;
scanf("%d",&n);
head=create(n);
print(head);
head=sort(head);
print(head);
}
发现可以
发现可以达到预期效果
但是,这个方法的循环次数太多,哪怕优化后,对内层加上了小于i就continue,也还是超时。
法二
既然改变链表结点顺序会超时,那么就退一步,我只要保持冒泡,将满足判断语句(后比前小)结构体里面的成员替换就好了。
比如1-5-4-6
当p指向5时,发现下一个的num更小,那么我就把下一个结点的num和我当前的num换一下,结点还是原来的结点,无需变动,只需改变成员变量就行了。
#include "stdio.h"
#include "malloc.h"
#define LEN sizeof(struct student)
struct student
{
long num;
int score;
struct student *next;
};
struct student *create(int n)
{
struct student *head=NULL,*p1=NULL,*p2=NULL;
int i;
for(i=1;i<=n;i++)
{ p1=(struct student *)malloc(LEN);
scanf("%ld",&p1->num);
scanf("%d",&p1->score);
p1->next=NULL;
if(i==1) head=p1;
else p2->next=p1;
p2=p1;
}
return(head);
}
void print(struct student *head)
{
struct student *p;
p=head;
while(p!=NULL)
{
printf("%8ld%8d",p->num,p->score);
p=p->next;
printf("\n");
}
}
struct student *insert(struct student *head, struct student *stud)
{ struct student *p0,*p1,*p2;
p1=head; p0=stud;
if(head==NULL)
{head=p0;}
else
{ while( (p0->num > p1->num) && (p1->next!=NULL) )
{ p2=p1; p1=p1->next;}
if( p0->num < p1->num )
{ if( head==p1 ) head=p0;
else p2->next=p0;
p0->next=p1; }
else { p1->next=p0;}
}
return(head);
}
struct student *del(struct student *head,long num)
{
struct student *p1,*p2;
p1=head;
while(p1!=NULL)
{
if(p1->num == num)
{
if(p1 == head) head=p1->next;
else p2->next=p1->next;
free(p1);
break;
}
p2=p1;
p1=p1->next;
}
return(head);
}
struct student *sort(struct student *head)
{
struct student *p1,*p2, *p3,*pre;
int i,j;
for(p1=head;p1!=NULL;p1=p1->next)
{
// p3=p1;
for(p2=p1->next;p2!=NULL;p2=p2->next)
{
if(p2->num<p1->num)
{
int t;
t = p1->num;
p1->num=p2->num;
p2->num=t;
t=p1->score;
p1->score=p2->score;
p2->score=t;
}
}
}
return head;
}
main()
{
struct student *head,*stu;
int n;
scanf("%d",&n);
head=create(n);
print(head);
head=sort(head);
print(head);
}
这样就快了很多。至于还有没有更好的方法,欢迎指出。