user-0 提问: 关于C语言链表求教

回复:
user: user-1
content: 引用 10 楼 waitti 的回复:[quote=引用 9 楼 cfjtaishan 的回复:] #include <stdio.h> #include <stdlib.h> #include <math.h>  const double esp = 1e-6;  struct stu_info {     char ID[12];     char name[10];     char sex[6];     char Class[10];     float score[3]; };  struct stu_msg {     struct stu_info info;     struct stu_msg *next; };   typedef int (*cmp)(struct stu_info *, struct stu_info *);  int compare_as_chinese (struct stu_info *a, struct stu_info *b) {     return  (a->score[0] > b->score[0]             && fabs(a->score[0] - b->score[0]) > esp); }  int compare_as_math (struct stu_info *a, struct stu_info *b) {     return  (a->score[1] > b->score[1]             && fabs(a->score[1] - b->score[1]) > esp); }  int compare_as_english(struct stu_info *a, struct stu_info *b) {     return  (a->score[2] > b->score[2]             && fabs(a->score[2] - b->score[2]) > esp); }  void swap_stu_info(struct stu_info *a, struct stu_info *b, cmp compare_as_score) {     struct stu_info tmp;      if (compare_as_score(a, b)) {         tmp = *a;         *a = *b;         *b = tmp;     } }  void sort(struct stu_msg **head, cmp cmp_score) {     struct stu_msg *p, *q;      for (p = *head; p; p = p->next)         for (q = *head; q->next; q = q->next)             swap_stu_info(&q->info, &q->next->info, cmp_score); }  int main(void) {      return 0; } 参考一下吧有点疑惑，就是，为什么不直接在含有数据结构那里建立链表，而是选择再创一个结构体；还有一点就是cmp_score并没有这个，就直接用吗？[/quote] 第一个问题：这样做可以更快速的拷贝数据（减少编码的行数），将数据和地址（next)分开有很多好处； 第二个问题：cmp_score是函数指针变量，即sort函数里第二个参数是一个函数指针变量，用于接收一个函数名； 调用sort函数时，第二个参数可以根据排序的要求传入compare_as_chinese或compare_as_math或compare_as_english

user: user-0
content: 引用 9 楼 cfjtaishan 的回复:#include <stdio.h> #include <stdlib.h> #include <math.h>  const double esp = 1e-6;  struct stu_info {     char ID[12];     char name[10];     char sex[6];     char Class[10];     float score[3]; };  struct stu_msg {     struct stu_info info;     struct stu_msg *next; };   typedef int (*cmp)(struct stu_info *, struct stu_info *);  int compare_as_chinese (struct stu_info *a, struct stu_info *b) {     return  (a->score[0] > b->score[0]             && fabs(a->score[0] - b->score[0]) > esp); }  int compare_as_math (struct stu_info *a, struct stu_info *b) {     return  (a->score[1] > b->score[1]             && fabs(a->score[1] - b->score[1]) > esp); }  int compare_as_english(struct stu_info *a, struct stu_info *b) {     return  (a->score[2] > b->score[2]             && fabs(a->score[2] - b->score[2]) > esp); }  void swap_stu_info(struct stu_info *a, struct stu_info *b, cmp compare_as_score) {     struct stu_info tmp;      if (compare_as_score(a, b)) {         tmp = *a;         *a = *b;         *b = tmp;     } }  void sort(struct stu_msg **head, cmp cmp_score) {     struct stu_msg *p, *q;      for (p = *head; p; p = p->next)         for (q = *head; q->next; q = q->next)             swap_stu_info(&q->info, &q->next->info, cmp_score); }  int main(void) {      return 0; } 参考一下吧有点疑惑，就是，为什么不直接在含有数据结构那里建立链表，而是选择再创一个结构体；还有一点就是cmp_score并没有这个，就直接用吗？

user: user-1
content: #include <stdio.h> #include <stdlib.h> #include <math.h>  const double esp = 1e-6;  struct stu_info {     char ID[12];     char name[10];     char sex[6];     char Class[10];     float score[3]; };  struct stu_msg {     struct stu_info info;     struct stu_msg *next; };   typedef int (*cmp)(struct stu_info *, struct stu_info *);  int compare_as_chinese (struct stu_info *a, struct stu_info *b) {     return  (a->score[0] > b->score[0]             && fabs(a->score[0] - b->score[0]) > esp); }  int compare_as_math (struct stu_info *a, struct stu_info *b) {     return  (a->score[1] > b->score[1]             && fabs(a->score[1] - b->score[1]) > esp); }  int compare_as_english(struct stu_info *a, struct stu_info *b) {     return  (a->score[2] > b->score[2]             && fabs(a->score[2] - b->score[2]) > esp); }  void swap_stu_info(struct stu_info *a, struct stu_info *b, cmp compare_as_score) {     struct stu_info tmp;      if (compare_as_score(a, b)) {         tmp = *a;         *a = *b;         *b = tmp;     } }  void sort(struct stu_msg **head, cmp cmp_score) {     struct stu_msg *p, *q;      for (p = *head; p; p = p->next)         for (q = *head; q->next; q = q->next)             swap_stu_info(&q->info, &q->next->info, cmp_score); }  int main(void) {      return 0; } 参考一下吧

user: user-0
content: 引用 3 楼 cfjtaishan 的回复:p1, p2无需申请空间，因为前面申请了空间，在for循环里, p1 = head已经将申请的空间的首地址覆盖了，p2 = p1->next，也是同样的覆盖，这样会导致内存泄漏。因为被覆盖后再也找不到刚刚申请的空间的位置了。 既然是排序操作，什么会有free操作呢？ 个人建议，为了好理解，可以考虑将数据部分交换，保留指针部分（地址部分） for (p1 = head; p1 != NULL; p1 = p1->next) 		for (p2 = p1->next; p2 != NULL; p2 = p2->next) 			if (p1->score[0] == p2->score[0]) 				if (p1->score[2] < p2->score[2])  				{ 					strcpy_s(t->Class, strlen(p2->Class) + 1, p2->Class); 					strcpy_s(p2->Class, strlen(p1->Class) + 1, p1->Class); 					strcpy_s(p1->Class, strlen(t->Class) + 1, t->Class); 					strcpy_s(t->name, strlen(p2->name) + 1, p2->name); 					strcpy_s(p2->name, strlen(p1->name) + 1, p1->name); 					strcpy_s(p1->name, strlen(t->name) + 1, t->name); 					strcpy_s(t->sex, strlen(p2->sex) + 1, p2->sex); 					strcpy_s(p2->sex, strlen(p1->sex) + 1, p1->sex); 					strcpy_s(p1->sex, strlen(t->sex) + 1, t->sex); 					strcpy_s(t->ID, strlen(p2->ID) + 1, p2->ID); 					strcpy_s(p2->ID, strlen(p1->ID) + 1, p1->ID); 					strcpy_s(p1->ID, strlen(t->ID) + 1, t->ID); 					t->score[0] = p2->score[0]; 					p2->score[0] = p1->score[0]; 					p1->score[0] = t->score[0]; 					t->score[1] = p2->score[1]; 					p2->score[1] = p1->score[1]; 					p1->score[1] = t->score[1]; 					t->score[2] = p2->score[2]; 					p2->score[2] = p1->score[2]; 					p1->score[2] = t->score[2]; 				}  struct student_message {     xxx data;    /*数据部分*/     struct student_message *next;    /*地址部分*/ }; 可是如果只是把数据部分调换，系统就会直接崩溃

user: user-0
content: 引用 2 楼 hzy_76 的回复:你有多處這樣的操作：  t = p2; p2 = p1; p1 = p2; free(t);  注意這是鏈表，刪除節點必須在斷開處重新連接，比如p->next = x，缺了這步操作，以後遍歷鏈表到這裏時就會訪問到已釋放的内存，所以崩潰了。  另外，你的代碼縮進不太好，看著眼花，建議盡量不要在一行中寫多個語句。但我现在不是删除节点，而是想让两个节点的内容调换，应该怎么修改呢

user: user-2
content: 数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633

user: user-1
content: p1, p2无需申请空间，因为前面申请了空间，在for循环里, p1 = head已经将申请的空间的首地址覆盖了，p2 = p1->next，也是同样的覆盖，这样会导致内存泄漏。因为被覆盖后再也找不到刚刚申请的空间的位置了。 既然是排序操作，什么会有free操作呢？ 个人建议，为了好理解，可以考虑将数据部分交换，保留指针部分（地址部分）   struct student_message {     xxx data;    /*数据部分*/     struct student_message *next;    /*地址部分*/ };

user: user-3
content: 你有多處這樣的操作：  t = p2; p2 = p1; p1 = p2; free(t);  注意這是鏈表，刪除節點必須在斷開處重新連接，比如p->next = x，缺了這步操作，以後遍歷鏈表到這裏時就會訪問到已釋放的内存，所以崩潰了。  另外，你的代碼縮進不太好，看著眼花，建議盡量不要在一行中寫多個語句。

user: user-0
content: 引用 7 楼 cfjtaishan 的回复:[quote=引用 6 楼 waitti 的回复:] [quote=引用 3 楼 cfjtaishan 的回复:] p1, p2无需申请空间，因为前面申请了空间，在for循环里, p1 = head已经将申请的空间的首地址覆盖了，p2 = p1->next，也是同样的覆盖，这样会导致内存泄漏。因为被覆盖后再也找不到刚刚申请的空间的位置了。 既然是排序操作，什么会有free操作呢？ 个人建议，为了好理解，可以考虑将数据部分交换，保留指针部分（地址部分） for (p1 = head; p1 != NULL; p1 = p1->next) 		for (p2 = p1->next; p2 != NULL; p2 = p2->next) 			if (p1->score[0] == p2->score[0]) 				if (p1->score[2] < p2->score[2])  				{ 					strcpy_s(t->Class, strlen(p2->Class) + 1, p2->Class); 					strcpy_s(p2->Class, strlen(p1->Class) + 1, p1->Class); 					strcpy_s(p1->Class, strlen(t->Class) + 1, t->Class); 					strcpy_s(t->name, strlen(p2->name) + 1, p2->name); 					strcpy_s(p2->name, strlen(p1->name) + 1, p1->name); 					strcpy_s(p1->name, strlen(t->name) + 1, t->name); 					strcpy_s(t->sex, strlen(p2->sex) + 1, p2->sex); 					strcpy_s(p2->sex, strlen(p1->sex) + 1, p1->sex); 					strcpy_s(p1->sex, strlen(t->sex) + 1, t->sex); 					strcpy_s(t->ID, strlen(p2->ID) + 1, p2->ID); 					strcpy_s(p2->ID, strlen(p1->ID) + 1, p1->ID); 					strcpy_s(p1->ID, strlen(t->ID) + 1, t->ID); 					t->score[0] = p2->score[0]; 					p2->score[0] = p1->score[0]; 					p1->score[0] = t->score[0]; 					t->score[1] = p2->score[1]; 					p2->score[1] = p1->score[1]; 					p1->score[1] = t->score[1]; 					t->score[2] = p2->score[2]; 					p2->score[2] = p1->score[2]; 					p1->score[2] = t->score[2]; 				}  struct student_message {     xxx data;    /*数据部分*/     struct student_message *next;    /*地址部分*/ }; 可是如果只是把数据部分调换，系统就会直接崩溃 [/quote] 不会崩溃，交换数据部分，不改变next指针的指向。如果你认为我的想法会导致程序崩溃，那么你理解我的交换方法有问题 建议将你的数据结构贴出来，我可以给你写个只交换数据部分，不修改next地址部分的排序[/quote]char ID[12]; 	char name[10]; 	char sex[6]; 	char Class[10]; 	float score[3]; 对分数进行排序，首先语文优先，是score[0]，然后在语文排好序的时候，对语文成绩相等的进行数学排序，同理再对英语

user: user-1
content: 引用 6 楼 waitti 的回复:[quote=引用 3 楼 cfjtaishan 的回复:] p1, p2无需申请空间，因为前面申请了空间，在for循环里, p1 = head已经将申请的空间的首地址覆盖了，p2 = p1->next，也是同样的覆盖，这样会导致内存泄漏。因为被覆盖后再也找不到刚刚申请的空间的位置了。 既然是排序操作，什么会有free操作呢？ 个人建议，为了好理解，可以考虑将数据部分交换，保留指针部分（地址部分） for (p1 = head; p1 != NULL; p1 = p1->next) 		for (p2 = p1->next; p2 != NULL; p2 = p2->next) 			if (p1->score[0] == p2->score[0]) 				if (p1->score[2] < p2->score[2])  				{ 					strcpy_s(t->Class, strlen(p2->Class) + 1, p2->Class); 					strcpy_s(p2->Class, strlen(p1->Class) + 1, p1->Class); 					strcpy_s(p1->Class, strlen(t->Class) + 1, t->Class); 					strcpy_s(t->name, strlen(p2->name) + 1, p2->name); 					strcpy_s(p2->name, strlen(p1->name) + 1, p1->name); 					strcpy_s(p1->name, strlen(t->name) + 1, t->name); 					strcpy_s(t->sex, strlen(p2->sex) + 1, p2->sex); 					strcpy_s(p2->sex, strlen(p1->sex) + 1, p1->sex); 					strcpy_s(p1->sex, strlen(t->sex) + 1, t->sex); 					strcpy_s(t->ID, strlen(p2->ID) + 1, p2->ID); 					strcpy_s(p2->ID, strlen(p1->ID) + 1, p1->ID); 					strcpy_s(p1->ID, strlen(t->ID) + 1, t->ID); 					t->score[0] = p2->score[0]; 					p2->score[0] = p1->score[0]; 					p1->score[0] = t->score[0]; 					t->score[1] = p2->score[1]; 					p2->score[1] = p1->score[1]; 					p1->score[1] = t->score[1]; 					t->score[2] = p2->score[2]; 					p2->score[2] = p1->score[2]; 					p1->score[2] = t->score[2]; 				}  struct student_message {     xxx data;    /*数据部分*/     struct student_message *next;    /*地址部分*/ }; 可是如果只是把数据部分调换，系统就会直接崩溃 [/quote] 不会崩溃，交换数据部分，不改变next指针的指向。如果你认为我的想法会导致程序崩溃，那么你理解我的交换方法有问题 建议将你的数据结构贴出来，我可以给你写个只交换数据部分，不修改next地址部分的排序

user: user-4
content: 在调试模式运行程序，崩溃了点中断，通过调用堆栈定位到相关代码，结合各变量值观察分析原因