[英]linked list insertion sort in c
程序应该对节点进行插入升序排序,首先它应该检查名称,如果名称相等,它应该对id进行排序,我不知道什么是不能正确排序的问题。
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
typedef struct nd{
int id;
char name[20];
float gpa;
struct nd *next;
}node;
typedef node *list;
//---------------------------------------------------------------
int insertlist(list *head,char *buffer)
{
list p,q,n;
int m,num,k,sc;
p=(list)malloc(sizeof(node));
num=sscanf(buffer,"%d %s %f",&(p->id),(p->name),(&p->gpa));
if(num!=3)
{
printf("info not complete\n");
free(p);
return 1;
}
else
{
if(!*head)
{
*head=p;
p->next = NULL;
}
//******** sorting tthe names and ids for equal names
else if(sc=strcmp((*head)->name,p->name)> 0 || ((sc == 0) && ((*head)->id > p->id)))
{//head is modified
p->next=*head;
*head=p;
}
else{
n=*head;
q=n->next;
while(q && ((sc=strcmp(q->name,p->name)<0) || ((sc == 0) && (q->id < p->id))))
{
n=q;
q=q->next;
}
n->next=p;
p->next=q;
}
}
return 0;
}
//------------------------------------------------------
int main()
{
int id,r;
list head,p;
FILE *fp;
char c,buffer[100],filename[10];
if ((fp=fopen("student.txt","r"))==NULL)
{
printf("error opening %s",filename);
exit(1);
}
else
{
head=NULL;
while(fgets(buffer,100,fp)!=NULL)
{
buffer[strlen(buffer)-1]=='\0';
r=insertlist(&head,buffer);
}
fclose(fp);
}
for(p=head;p!=NULL;p=p->next)
printf("%d %s %f\n\n",p->id,p->name,p->gpa);
}
student.txt
的内容示例:
121513 ala 45.00
121510 wang 21.00
145852 frank 26.00
151515 ala 25.00
head是一个指针,所以为了在函数中更改它,你需要传递一个指针。 指向指针的指针。
声明如下:
int insertlist(list **head,char *buffer)
像这样称呼它:
r=insertlist(&(&head),buffer);
然后在功能变化的任何地方你引用它来取消引用指针。
首先,解决这个问题:
buffer[strlen(buffer)-1]=='\0';
这是一次平等比较; 不是作业。 我相信你试图在缓冲区末尾抛出换行符。 如果是这种情况,您可能需要确保它有一个新行开始抛出(输入文件的最后一行,例如可能不会以一个结尾。无论如何,这仍然是破坏的,需要修复。
接下来,您的排序循环存在问题。 我在下面加一个希望更容易阅读,因此理解,删除了逻辑缺陷(以及相当多的其他课外活动):
int insertlist(list *head, char *buffer)
{
list p=NULL, q=NULL;
int sc=0;
/* allocate new node */
p = calloc(1, sizeof(*p));
if(3 != sscanf(buffer,"%d %s %f",&(p->id),(p->name),(&p->gpa)))
{
printf("info not complete\n");
free(p);
return 1;
}
/* initially wire p->next to our list head. then, walk list,
advancing p->next. break on first "less" condition */
p->next = *head;
while (p->next)
{
/* broken out here for clarity; break on first "less" */
sc = strcmp(p->name, p->next->name);
if (sc < 0 || (sc == 0 && p->id < p->next->id))
break;
q = p->next;
p->next = q->next;
}
/* non-null means we wire q->next to p */
if (q)
q->next = p;
/* else p is the new head; what head was prior is already in p->next */
else
*head = p;
return 0;
}
使用以下输入文件进行测试:
0001 Brook 3.50
0002 James 3.51
0003 Katie 3.52
0004 James 3.87
0005 Brook 2.70
结果:
1 Brook 3.500000
5 Brook 2.700000
2 James 3.510000
4 James 3.870000
3 Katie 3.520000
我强烈建议您在尝试修复这些问题时以及在想要查看代码如何工作时单步执行调试器中的代码。
最后,不要侮辱伤害,你永远不会释放你的名单。 即它在程序退出时泄漏内存,这仅次于在执行期间以“坏”级别泄漏内存。 走那个列表并释放那个记忆。 进入是一个好习惯。
编辑 OP请求释放链表:
现在,在return
语句结束之前的main()
就足够了。 在某些时候,您应该考虑编写一个函数来为您执行此操作:
while (head)
{
list p=head;
head=head->next;
free(p);
}
您的排序问题是运算符优先级之一
<
和>
具有比=
更高的优先级,这意味着它将首先被评估,然后将进行赋值。
所以你的字符串在这两个地方比较:
else if(sc=strcmp((*head)->name,p->name)> 0 || ((sc == 0) && ((*head)->id > p->id)))
...
while(q && ((sc=strcmp(q->name,p->name)<0) || ((sc == 0) && (q->id < p->id))))
错了。 sc
得到strcmp((*head)->name,p->name)> 0
和strcmp(q->name,p->name)<0
(注意这将始终为1
或0
,永远不会-1
)
如果您只是调整代码:
else if((sc=strcmp((*head)->name,p->name))> 0 || ((sc == 0) && ((*head)->id > p->id)))
...
while(q && (((sc=strcmp(q->name,p->name))<0) || ((sc == 0) && (q->id < p->id))))
你会看到它有效。 故事的道德:不要试图用你的parens或括号来吝啬,它不会花费你更多的东西,它会使代码更清晰,它可以节省你这样的调试头痛。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.