| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1080 人关注过本帖
标题:运行错误:从两链表中删除相同学号的结点,求帮助!
只看楼主 加入收藏
a4811
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:100
专家分:107
注 册:2012-12-20
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:26 
运行错误:从两链表中删除相同学号的结点,求帮助!
程序代码:
/*有2个链表a和b,设结点中包括学号、姓名。从a链中删去与b链中
有相同学号的那些结点.*/
#include<stdlib.h>
#include"stdio.h"
typedef struct student
{
    int num;
    char name[20];
    struct student *next;
}Code;
void main()
{
    Code *Creat(int length);
    Code *Delete(Code *ahead,Code *bhead);
    void Print(Code *head);
    Code *ahead,*bhead;
    int a_length,b_length;
    printf("input length of list_a:\n");
    scanf("%d",&a_length);
    ahead=Creat(a_length);
    Print(ahead);
    printf("input length of list_b:\n");
    scanf("%d",&b_length);
    bhead=Creat(b_length);
    Print(bhead);
    ahead=Delete(ahead,bhead);
    Print(ahead);
}

//建立链表函数
Code *Creat(int length)
{
    Code *p1,*p2,*head;
    int i;
    printf("Now,input the students' information:\n");
    for(i=0;i<length;i++)
    {
        p1=(Code *)malloc(sizeof(Code));
        if(i==0)
            head=p2=p1;
        else
            p2->next=p1;
        p2=p1;
        scanf("%d %s",&p1->num,p1->name);
    }
    p1->next=NULL;
    return head;
}

//输出链表函数
void Print(Code *head)
{
    Code *p;
    p=head;
    if(head!=NULL)
        do
        {
            printf("number:%d  name:%s\n",p->num,p->name);
            p=p->next;
        }while(p!=NULL);
}

//删除相同学号函数
Code *Delete(Code *ahead,Code *bhead)
{
    Code *pa1,*pa2,*pb1;
    pb1=bhead;
    while(pb1!=NULL)             //让b表中的每个结点和a表比较
    {
        pa1=ahead;
        while((pb1->num!=pa1->num)&&(pa1!=NULL))
        {
            pa2=pa1;             //pa2始终指向pa1的前一个结点
            pa1=pa1->next;
        }
        if(pb1->num==pa1->num)         //两链表中学号相同
            if(pa1==ahead)             //a链表中当前结点为第一个结点
                ahead=pa1->next;       //使ahead指向a链第二个结点
            else
                pa2->next=pa1->next;   //删除pa1所指结点
        pb1=pb1->next;                 //pb1移向下一个结点
    }
    return ahead;
}
//问题出在 删除学号 这个函数,一直找不出原因。希望大家多多帮忙,找出问题。

[ 本帖最后由 a4811 于 2013-1-5 21:04 编辑 ]
搜索更多相关主题的帖子: 姓名 
2013-01-05 18:30
azzbcc
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:江西财经大学
等 级:贵宾
威 望:81
帖 子:3293
专家分:12919
注 册:2012-11-4
收藏
得分:5 
回复 楼主 a4811
亏我研究那般许久,毛线啊

错误根本不在建立那。。。

void Print(Code *head)
{
     Code *p;
     p=head;
     if(head!=NULL)
         do
         {
             printf("number:d%  name:%s\n",p->num,p->name);
             p=p->next;
         }while(p!=NULL);
 }
 就是这个。。。


[fly]存在即是合理[/fly]
2013-01-05 19:00
a4811
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:100
专家分:107
注 册:2012-12-20
收藏
得分:0 
回复 2楼 azzbcc
兄弟,输出函数哪里有问题 ,你说明白撒。
2013-01-05 19:17
a4811
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:100
专家分:107
注 册:2012-12-20
收藏
得分:0 
回复 2楼 azzbcc
OK。
我知道了。
2013-01-05 19:42
a4811
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:100
专家分:107
注 册:2012-12-20
收藏
得分:0 
通宵等待.
2013-01-05 21:07
神龙赖了
Rank: 10Rank: 10Rank: 10
来 自:萨塔星
等 级:青峰侠
威 望:2
帖 子:711
专家分:1788
注 册:2012-10-13
收藏
得分:5 
这个程序删除那部分有个概念错误
如果要删除就直接不记录它的地址
这样做有点内存泄露的感觉,
不对,肯定内存泄露了...
删除的时候应该是用free释放其空间后才能删除其地址
程序代码:
 while((pb1->num!=pa1->num)&&(pa1!=NULL)&&(pb1 != NULL))
        {
            pa2=pa1;             //pa2始终指向pa1的前一个结点
            pa1=pa1->next;
        }

我调试发现当输入不正确时pa1 ->next指向的不是预定的也不是NULL,是个乱码似的值
好吧看来还得改改...

I have not failed completely
2013-01-05 22:08
神龙赖了
Rank: 10Rank: 10Rank: 10
来 自:萨塔星
等 级:青峰侠
威 望:2
帖 子:711
专家分:1788
注 册:2012-10-13
收藏
得分:0 
程序代码:
/*有2个链表a和b,设结点中包括学号、姓名。从a链中删去与b链中
有相同学号的那些结点.*/
#include <stdlib.h>
#include <stdio.h>

typedef struct student
{
    int num;
    char name[20];
    struct student *next;
}Code;

void main()
{
    Code *Creat(int length);
    Code *Delete(Code *ahead,Code *bhead);
    void Print(Code *head);
    Code *ahead,*bhead;
    int a_length,b_length;
    printf("input length of list_a:\n");
    scanf("%d",&a_length);
    ahead=Creat(a_length);
    Print(ahead);
    printf("input length of list_b:\n");
    scanf("%d",&b_length);
    bhead=Creat(b_length);
    Print(bhead);
    ahead=Delete(ahead,bhead);
    Print(ahead);
}

//建立链表函数
Code *Creat(int length)
{
    Code *p1,*p2,*head;
    int i;
    printf("Now,input the students' information:\n");
    for(i=0;i<length;i++)
    {
        p1=(Code *)malloc(sizeof(Code));
        if(i==0)
            head=p2=p1;
        else
            p2->next=p1;
        p2=p1;
        scanf("%d %s",&p1->num,p1->name);
    }
    p1->next=NULL;
    return head;
}

//输出链表函数
void Print(Code *head)
{
    Code *p;
    p=head;
    if(head!=NULL)
        do
        {
            printf("number:%d  name:%s\n",p->num,p->name);
            p=p->next;
        }while(p!=NULL);
}

//删除相同学号函数
Code *Delete(Code *ahead,Code *bhead)
{
    Code *pa1,*pa2,*pb1;
    pb1=bhead;

    while(pb1!=NULL)             //让b表中的每个结点和a表比较
    {
        pa1=ahead;
       
        while((pa1!=NULL)&&(pb1 != NULL)&&(pb1->num!=pa1->num))
        {
            printf("%d\n",pa1 ->num);
            pa2=pa1;             //pa2始终指向pa1的前一个结点
            pa1=pa1->next;
            printf("pa1 == %p\n",pa1);
        }
        printf("运行\n");

        if(0)
        printf("next == %s\n",pa1 ->next ->name);
       
        if(pb1 == NULL)
            break;

        if(  pa1 != NULL)         //两链表中学号相同
        {
            if(pb1->num==pa1->num)
            {
            if(pa1 == ahead)             //a链表中当前结点为第一个结点
                ahead=ahead->next;       //使ahead指向a链第二个结
            else
                pa2->next=pa1->next;   //删除pa1所指结点
            }
        }
        pb1=pb1->next;                 //pb1移向下一个结点
        printf("运行2\n");
    }
    return ahead;
}

关于那些运行什么的是我测试时用的
问题在于:
程序代码:
  pa1=ahead;
        while((pb1->num!=pa1->num)&&(pa1!=NULL))    /* 计算的顺序是从左往右的,也就是说(pb1->num!=pa1->num)这一条会先比较,然后才是pa1!=NULL,但是当pa1为NULL时pa1->num这个操作就是致命的...程序直接崩溃,pa1!=NULL根本没有机会运行了 */
        {
            pa2=pa1;             //pa2始终指向pa1的前一个结点
            pa1=pa1->next;
        } if(pb1->num==pa1->num)         //两链表中学号相同    当pa1 == NULL时结果就再一次悲剧了...
            if(pa1==ahead)             //a链表中当前结点为第一个结点
                ahead=pa1->next;       //使ahead指向a链第二个结点
            else
                pa2->next=pa1->next;   //删除pa1所指结点


对了,我改了,可以运行,但是这个程序仍不正确
因为它会引起内存泄漏,不过你用pa2本来应该是这目的吧?
释放内存很简单,毕竟是你的程序,自己做做试试吧
要考虑到释放结构后结构中的next中的地址也会消失
记得这一条就不会出错了,祝你好运

I have not failed completely
2013-01-05 22:56
yaobao
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:4
帖 子:1854
专家分:4121
注 册:2012-10-25
收藏
得分:5 
呵呵,是这句话的问题吧
 while((pb1->num!=pa1->num)&&(pa1!=NULL))
        {
            pa2=pa1;             //pa2始终指向pa1的前一个结点
            pa1=pa1->next;
        }
红色的判断语句在每次循环开始都会被执行一次用以决定循环是否继续,但是这有个问题,那就是最后一次应该跳出时刚刚执行了pa1=pa1->next语句,这是的pa1指向空,这样的比较行为是不是合法我们也不知道,通常的做法是比较pa1->next是否等于NULL,而不是pa1是否为空,我试着改成pa1->next!=NULL之后问题却是解决了。
但是又有个问题我测试了下代码
#include<stdio.h>
main(){
    char *q=NULL,*p=NULL;
    printf("%d",p==q);
}
发现一切正常,所以pa1!=NULL这样的比较就是合法的,之后我发现问题好像出在pb1->num!=pa1->num
pa1都等于NULL了,还怎么pa1->num啊。
貌似是吧

认认真真的学习,踏踏实实的走路:戒骄戒躁!!!
2013-01-05 22:59
yaobao
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:4
帖 子:1854
专家分:4121
注 册:2012-10-25
收藏
得分:0 
还有,记得释放内存

认认真真的学习,踏踏实实的走路:戒骄戒躁!!!
2013-01-05 23:00
a4811
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:100
专家分:107
注 册:2012-12-20
收藏
得分:0 
回复 9楼 yaobao
确实,我刚刚将"pa1!=NULL"改成"pa1->next!=NULL".运行正确。你跟我细说下这这二者的区别吗?我老是帮它们俩等价,分不清在循环中到底该使用哪个。
如果这个我没弄清楚,以后在其它程序中还会犯这样的区别,bao哥。
2013-01-05 23:57
快速回复:运行错误:从两链表中删除相同学号的结点,求帮助!
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.026985 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved