| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1586 人关注过本帖
标题:线性单链表合并问题
只看楼主 加入收藏
super_lz
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2017-7-12
结帖率:90%
收藏
 问题点数:0 回复次数:2 
线性单链表合并问题
问题:  就是最后的Status MergeList_L()函数调用的时候程序会崩溃掉,麻烦帮我看看。  谢谢。

#include <stdio.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1  
#define OVERFLOW -2

typedef int Status;
typedef int ElemType;

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode, *Link, *Position;

typedef struct
{
    Link head, tail;
    int len;
}LinkList;

Status MakeNode(Link *p, ElemType e);
void FreeNode(Link *p);
Status InitList(LinkList *L);
Status ClearList(LinkList *L);
Status Destory(LinkList *L);
Status InsertList(LinkList *L, Link s);
void Traverse(LinkList *L);
void Append(LinkList *L, Link s);
ElemType GetCurElem(Link p);
Status IsEmpty(LinkList *L);
Position PriorPos(LinkList L, Link p);
Position NextPos(Link p);
Status compare(ElemType e1,ElemType e2);
Status ListTravese(LinkList L, void (*visit)(ElemType));
Status MergeList_L(LinkList *La, LinkList *Lb, LinkList *Lc, int (*compare)(ElemType e1, ElemType e2));
Status DelFirst(LinkList L, Link h, Link *q);
void FreeNode(Link p);


void main()
{
    Link p, s, h;
    LinkList L;
    Status i;
    int j;
    Link q;
    ElemType e;

//    //归并链表
    LinkList La, Lb, Lc;
   
    if(!InitList(&La))   //初始化空的线性表La不成功
        exit(-1);   //异常退出

    for(j = 1; j <= 10; j++)
    {
        MakeNode(&p, j*3);
        InsertList(&La, p);
    }
    printf("La:\n");
    Traverse(&La);

    if(!InitList(&Lb))   //初始化空的线性表Lb不成功
        exit(-1);   //异常退出

    for(j = 1; j <= 10; j++)
    {
        MakeNode(&p, j*2);
        InsertList(&Lb, p);
    }
    printf("Lb:\n");
    Traverse(&Lb);

//    InitList(&Lc);
    MergeList_L(&La, &Lb, &Lc, compare);
    printf("Lc:\n");
    Traverse(&Lc);

    Destory(&La);
    Destory(&Lb);
}

//分配由p指向e的结点
Status MakeNode(Link *p, ElemType e)
{
    (*p) = (Link)malloc(sizeof(LNode));
    if(!(*p))
        return ERROR;

    (*p)->data = e;
    return OK;
}

void FreeNode(Link *p)
{
    free(*p);
    (*p) = NULL;
}

//创造一个空的线性表
Status InitList(LinkList *L)
{
    Link p;
    p = (Link)malloc(sizeof(LNode));
    if(!p)
        return ERROR;

    p->next = NULL;
    L->head = L->tail = p;
    L->len = 0;
    return OK;
}
//将线性表L重置为空表,并释放原链表的空间
Status ClearList(LinkList *L)
{
    Link p, q;

    if(L->head != L->tail)
    {
        p = q = L->head->next;
        L->head = NULL;

        while(p < L->tail)
        {
            p = q->next;
            free(q);
            q = p;
        }

        free(q);

        L->tail = L->head;
        L->len = 0;
    }

    return OK;
}

//销毁相信链表L, L不在存在
Status Destory(LinkList *L)
{
    ClearList(L);
    FreeNode(&(L->head));   //释放头结点
    L->tail = NULL;
    L->len = 0;
    return OK;
}

//将s所指结点插入线性表
Status InsertList(LinkList *L, Link s)   
{
   
    L->tail->next = s;
    L->tail = s;
    L->len++;
    return OK;
}

void Traverse(LinkList *L)
{
    Link p;
    p = L->head->next;
    int i;

    for(i = 0; i < L->len; i++)
    {

        printf("No.%d: %d\n", i, p->data);
        p = p->next;
    }
    printf("The length of list is %d.\n", L->len);
}

//将指针s所指(彼此以指针相链)的一串结点链接在线性表L的最后一个结点
//之后,并改变链表L的指针指向新的尾结点
void Append(LinkList *L, Link s)
{
     int i=1;  
    L->tail->next = s;  //s接到L的尾部  
    while(s->next)        //计算s的长度  
    {  
        i++;  
        s = s->next;  
    }  
    L->tail = s;        //L的尾指针变成s的尾指针  
    L->len+=i;          //增加长度
    printf("i = %d\n", i);
}


//已知p指向线性链表中的一个结点,返回p所指元素的值
ElemType GetCurElem(Link p)
{
    return p->data;
}

//若线性表为空,则返回TRUE,否则饭后FALSE
Status IsEmpty(LinkList *L)
{
    if(!L->head->next)
        return TRUE;
    else
        return FALSE;
}


////已知p指向线性表L中的一个结点,返回p所指结点的直接后继的位置
//若无后继,返回NULL
Position NextPos(Link p)
{
        return p->next;
}

Status compare(ElemType e1,ElemType e2)  
{  
    return e1 <= e2;  
}  



//依次对L的每个元素调用函数visit()。一旦visit()失败,则操作失败
Status ListTravese(LinkList L, void (*visit)(ElemType))
{
    Link p;
    p = L.head->next;
    int i;

    for(i = 0; i < L.len; i++)
    {
        visit(p->data);
        p = p->next;
    }
    printf("\n");
    return OK;
}

//已知h指向线性链表的头结点,删除链表中的第一个结点并以q返回
Status DelFirst(LinkList L, Link h, Link *q)
{
    Link p;
    MakeNode(q, 0);   //初始胡q;
    (*q)->data = h->next->data;   //把第一个数据结点的值赋值给q

    p = h->next;   //使p指向第一个数据结点
    h->next = p->next;
    free(p);
   
    L.len --;
    return OK;
}

//释放链表L的头结点
void FreeNode(Link p)
{
    free(p);
}

//已知单链表La和Lb的元素按值非递减排列
//归并La和Lb得到新的单链表Lc,Lc的元素也按值非递减排列
Status MergeList_L(LinkList *La, LinkList *Lb, LinkList *Lc, int (*compare)(ElemType e1, ElemType e2))
{
    Link ha, hb, pa, pb, q;
    ElemType a, b;

    if(!InitList(Lc))   //存储空间分配失败
    {
        printf("Lc内存分配失败");
        return ERROR;
    }
        
   
    ha = La->head;
    hb = Lb->head;

    pa = NextPos(ha);
    pb = NextPos(hb);

    while(!IsEmpty(La)&&!IsEmpty(Lb))   //pa和pb非空
    {
        a = GetCurElem(pa);
        b = GetCurElem(pb);
        
        if(compare(a, b))   //a<=b
        {
            DelFirst(*La, ha, &q);   //删除La中的第一个元素,并以q返回
            Append(Lc, q);   //DelFirst 返回的q插入到Lc中
            pa = NextPos(ha);
        }
        else
        {
            DelFirst(*Lb, hb, &q);
            Append(Lc, q);
            pa = NextPos(hb);
        }
        
        if(pa)   //如果最后La中还剩有元素,全部合并到Lc中
            Append(Lc, ha);
        else
            Append(Lc, hb);

        FreeNode(ha);   //释放La的头结点
        FreeNode(hb);   //释放Lb的头结点
    }
    return OK;
}
搜索更多相关主题的帖子: Status next Link 结点 return 
2018-04-02 23:28
lanke711
Rank: 9Rank: 9Rank: 9
来 自:流浪在天国之路
等 级:蜘蛛侠
威 望:7
帖 子:317
专家分:1437
注 册:2015-7-16
收藏
得分:0 
回复 楼主 super_lz
看着你的代码,我很头疼。你这是写的C呢?还是写的C++呢?
我更相信你创建的是.cpp文件,而不是.c文件。。。

下面一些发现的问题,我用颜色标记了。请注意看看一下。
或许还有我没发现的问题。

#include <stdio.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1  
#define OVERFLOW -2

typedef int Status;
typedef int ElemType;

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode, *Link, *Position;

typedef struct
{
    Link head, tail;
    int len;
}LinkList;

Status MakeNode(Link *p, ElemType e);
void FreeNode(Link *p);           //这里有个FreeNode(Link *p)
Status InitList(LinkList *L);
Status ClearList(LinkList *L);
Status Destory(LinkList *L);
Status InsertList(LinkList *L, Link s);
void Traverse(LinkList *L);
void Append(LinkList *L, Link s);
ElemType GetCurElem(Link p);
Status IsEmpty(LinkList *L);
Position PriorPos(LinkList L, Link p);
Position NextPos(Link p);
Status compare(ElemType e1, ElemType e2);
Status ListTravese(LinkList L, void(*visit)(ElemType));
Status MergeList_L(LinkList *La, LinkList *Lb, LinkList *Lc, int(*compare)(ElemType e1, ElemType e2));
Status DelFirst(LinkList L, Link h, Link *q);
void FreeNode(Link p);                //这里又有个FreeNode()?  Why?C没有重载这个机制


void main()
{
    Link p, s, h;
    LinkList L;
    Status i;
    int j;
    Link q;
    ElemType e;

    //    //归并链表
    LinkList La, Lb, Lc;

    if (!InitList(&La))   //初始化空的线性表La不成功
        exit(-1);   //异常退出

    for (j = 1; j <= 10; j++)
    {
        MakeNode(&p, j * 3);
        InsertList(&La, p);
    }
    printf("La:\n");
    Traverse(&La);

    if (!InitList(&Lb))   //初始化空的线性表Lb不成功
        exit(-1);   //异常退出

    for (j = 1; j <= 10; j++)
    {
        MakeNode(&p, j * 2);
        InsertList(&Lb, p);
    }
    printf("Lb:\n");
    Traverse(&Lb);

    //    InitList(&Lc);
    MergeList_L(&La, &Lb, &Lc, compare);
    printf("Lc:\n");
    Traverse(&Lc);

    Destory(&La);
    Destory(&Lb);
}

//分配由p指向e的结点
Status MakeNode(Link *p, ElemType e)
{
    (*p) = (Link)malloc(sizeof(LNode));
    if (!(*p))
        return ERROR;

    (*p)->data = e;
    return OK;
}

void FreeNode(Link *p)
{
    free(*p);
    (*p) = NULL;
}

//创造一个空的线性表
Status InitList(LinkList *L)
{
    Link p;
    p = (Link)malloc(sizeof(LNode));
    if (!p)
        return ERROR;

    p->next = NULL;
    L->head = L->tail = p;
    L->len = 0;
    return OK;
}
//将线性表L重置为空表,并释放原链表的空间
Status ClearList(LinkList *L)
{
    Link p, q;

    if (L->head != L->tail)
    {
        p = q = L->head->next;
        L->head = NULL;

        while (p < L->tail)
        {
            p = q->next;
            free(q);
            q = p;
        }

        free(q);

        L->tail = L->head;
        L->len = 0;
    }

    return OK;
}

//销毁相信链表L, L不在存在
Status Destory(LinkList *L)
{
    ClearList(L);
    FreeNode(&(L->head));   //释放头结点
    L->tail = NULL;
    L->len = 0;
    return OK;
}

//将s所指结点插入线性表
Status InsertList(LinkList *L, Link s)
{

    L->tail->next = s;
    L->tail = s;
    L->len++;
    return OK;
}

void Traverse(LinkList *L)
{
    Link p;
    p = L->head->next;
    int i;

    for (i = 0; i < L->len; i++)
    {

        printf("No.%d: %d\n", i, p->data);
        p = p->next;
    }
    printf("The length of list is %d.\n", L->len);
}

//将指针s所指(彼此以指针相链)的一串结点链接在线性表L的最后一个结点
//之后,并改变链表L的指针指向新的尾结点
void Append(LinkList *L, Link s)
{
    int i = 1;
    L->tail->next = s;  //s接到L的尾部  
    while (s->next)        //计算s的长度     //到这里就崩溃了。因为s没有接收到的q传递
    {
        i++;
        s = s->next;
    }
    L->tail = s;        //L的尾指针变成s的尾指针  
    L->len += i;          //增加长度
    printf("i = %d\n", i);
}


//已知p指向线性链表中的一个结点,返回p所指元素的值
ElemType GetCurElem(Link p)
{
    return p->data;
}

//若线性表为空,则返回TRUE,否则饭后FALSE
Status IsEmpty(LinkList *L)
{
    if (!L->head->next)
        return TRUE;
    else
        return FALSE;
}


////已知p指向线性表L中的一个结点,返回p所指结点的直接后继的位置
//若无后继,返回NULL
Position NextPos(Link p)
{
    return p->next;
}

Status compare(ElemType e1, ElemType e2)
{
    return e1 <= e2;
}



//依次对L的每个元素调用函数visit()。一旦visit()失败,则操作失败
Status ListTravese(LinkList L, void(*visit)(ElemType))
{
    Link p;
    p = L.head->next;
    int i;

    for (i = 0; i < L.len; i++)
    {
        visit(p->data);
        p = p->next;
    }
    printf("\n");
    return OK;
}

//已知h指向线性链表的头结点,删除链表中的第一个结点并以q返回
Status DelFirst(LinkList L, Link h, Link *q)
{
    Link p;
    MakeNode(q, 0);   //初始胡q;
    (*q)->data = h->next->data;   //把第一个数据结点的值赋值给q

    p = h->next;   //使p指向第一个数据结点
    h->next = p->next;
    free(p);

    L.len--;
    return OK;
}

//释放链表L的头结点
void FreeNode(Link p)
{
    free(p);
}

//已知单链表La和Lb的元素按值非递减排列
//归并La和Lb得到新的单链表Lc,Lc的元素也按值非递减排列
Status MergeList_L(LinkList *La, LinkList *Lb, LinkList *Lc, int(*compare)(ElemType e1, ElemType e2))
{
    Link ha, hb, pa, pb, q;
    ElemType a, b;

    if (!InitList(Lc))   //存储空间分配失败
    {
        printf("Lc内存分配失败");
        return ERROR;
    }


    ha = La->head;
    hb = Lb->head;

    pa = NextPos(ha);
    pb = NextPos(hb);

    while (!IsEmpty(La) && !IsEmpty(Lb))   //pa和pb非空
    {
        a = GetCurElem(pa);
        b = GetCurElem(pb);

        if (compare(a, b))   //a<=b
        {
            DelFirst(*La, ha, &q);   //删除La中的第一个元素,并以q返回
            Append(Lc, q);   //DelFirst 返回的q插入到Lc中
            pa = NextPos(ha);
        }
        else
        {
            DelFirst(*Lb, hb, &q);
            Append(Lc, q);    //这个q没有传进去。导致崩溃的原因所在。
            pa = NextPos(hb);
        }

        if (pa)   //如果最后La中还剩有元素,全部合并到Lc中
            Append(Lc, ha);
        else
            Append(Lc, hb);

       FreeNode(ha);   //问题来了。你这个FreeNode,是调用哪一个FreeNode?
        FreeNode(hb);   //同上

    }
    return OK;
}



[此贴子已经被作者于2018-4-4 13:50编辑过]


普通人之所以普通,是因为他们普遍有一个通病,那就是认为自己永远普通。
千夫所指,我亦坚持。就算被所有人误解,我也照样守护这一切。
我们总是觉得,这些灵魂的表情,傲慢自大,目中无人,其实,真正目中无人的是我们。它们傲慢的不过是表情,而我们傲慢的却是行为!
记得,是为了忘记!
只要想着有那么一天,我就能忍受现在的每一天!
灾难并不可怕,可怕的是心中没有了希望。
你以为我在天堂,其实我正在路上。
当你觉得自己走不到终点的时候,请不要放弃。或许你的对手也是这种感觉。
2018-04-04 03:28
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
发现链表有环,还要看看具体原因才行~

 pa = NextPos(hb);
 这里应该是pb=NextPos(b);吧~


还有
        if (pa)   //如果最后La中还剩有元素,全部合并到Lc中
            Append(Lc, ha);
        else
            Append(Lc, hb);

这个应该写在循环外边吧~

要在MakeNode里面加一行(*p)->next=NULL;不然遍历的时候用p->next这个条件来判断就见笑了~
while (p <L->tail)这里最好写成p->next!=L->tail,虽然不改也可以正常运行,不过释放空间重新分配内存那就很难说了,用!=容易理解而且不会碰到一些意外的bug~


当然修改后还有些小问题,至于具体就留给有心的认真看看了~


[此贴子已经被作者于2018-4-5 13:37编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-04-05 10:24
快速回复:线性单链表合并问题
数据加载中...
 
   



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

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