注册 登录
编程论坛 C语言论坛

两个集合求并集(用链表的方式)

eagle4959445 发布于 2017-05-23 14:17, 8834 次点击
#include<stdio.h>
#include<stdlib.h>

struct LNode
{
    int data;
    struct LNode *next;
};
typedef struct LNode *LinkList;//表的头指针类型

void CreateListF(LinkList L, int a[], int n);
int ListLength(LinkList L);//求表的长度
int GetElem(LinkList L, int i, int *e);
int LocateElem(LinkList L, int x);
int ListInsert(LinkList *L, int x, int l);
void Union(LinkList *La, LinkList Lb);

void CreateListF(LinkList L, int a[], int n)//创建一个单链表
{
    LinkList s;
    int i;
    L=(LinkList *)malloc(sizeof(LinkList));//创建头结点
    L->next=NULL;
    for(i=0; i<n; i++)
    {
        s=(LinkList *)malloc(sizeof(LinkList));//创建新结点
        s->data=a[i];
        s->next=L->next;
        L->next=s;
    }
}

int ListLength(LinkList L)//求表的长度
{
    int i=0;
    LinkList p=L->next;
    while(p!=NULL)
    {
        i++;
        p=p->next;
    }
    return i;
}

int GetElem(LinkList L, int i, int *e)
{
    int j=1;
    LinkList p;
    p=L->next;
    if(i<1||i>ListLength(L))
    return 0;
    while(j<i)
    {
        p=p->next;
        j++;
    }
    e=p->data;
    return (1);
}

int LocateElem(LinkList L, int x)//判断运算
{
    int i=1;
    struct LNode *p;
    p=L->next;
    while(p!= NULL &&p->data!=x)
    {
        p=p->next;
        i++;
    }
    if(p==NULL)
    return (0);
    else return(i);
}

int ListInsert(LinkList *L, int x, int i)
{
    int j=1;
    LinkList p=L, s;
    s=(LinkList *)malloc(sizeof(LinkList));
    s->data=x;
    s->next=NULL;
    if(i<1||i>ListLength(L)+1)
    return 0;
    while(j<i)
    {
        p= p->next;
        j++;
    }
    s->next=p->next;
    p->next=s;
    return 1;
}
void Union(LinkList *La, LinkList Lb)
{
    int e;
    int La_len, Lb_len;
    int i;
    La_len=ListLength(La);
    Lb_len=ListLength(Lb);
    for(i=1; i<=Lb_len; i++)
    {
        GetElem(Lb, i, e);
        if(!LocateElem(La, e))
        ListInsert(La, ++La_len, e);
    }
}

int main(void)
{
   
    struct LNode A[60];
    struct LNode B[30];
    int i, a;
   
    printf("请输入A:");
    for(i=0; A[i].data!='\0' ; i++)
    {scanf("%d", &A[i].data);}
    printf("请输入B:");
    for(i=0; i<3; i++)
    {scanf("%d", &B[i].data);}
   
    printf("A是:");
    CreateListF(A, A->data, 3);
 CreateListF(B, B->data, 3);
 Union(A, B);
   
    for(i=0; i<6; i++)
    {printf("%d", A[i].data);}   
    return 0;
}

大神们帮我看看我哪里错了
7 回复
#2
Emotiona2017-05-24 03:14
到处都是逻辑问题。你自己一个函数的去调试
#3
Emotiona2017-05-25 21:02
你这个逻辑错误太多了,两个集合求并集根本不需要那么多的操作,多余的给你注释了。多余部分也有很多错误,前面部分给你改了,后面多余的都没帮你看了。
程序代码:
#include<stdio.h>
#include<stdlib.h>

struct LNode
{
    int data;
    struct LNode *next;
};
typedef struct LNode LinkList;//表的头指针类型         //定义的结构体别名为指针类型

LinkList *CreateListF(int a[], int n);       //把结构体指针定义到创建函数中
int ListLength(LinkList L);//求表的长度
int GetElem(LinkList *p, int i, int *e);        //要用指针才能找到下一个地址
int LocateElem(LinkList L, int x);
int ListInsert(LinkList *L, int x, int l);
LinkList *Union(LinkList *La, LinkList *Lb);         //参数一个是指针, 一个不是指针。。。

LinkList *CreateListF(int *a, int n)//创建一个单链表
{
    LinkList *L, *s, *s1;
    int i;

    L = NULL;
    for(i=0; i<n; i++)
    {

        s=(LinkList *)malloc(sizeof(LinkList));//创建新结点
        if(L == NULL)                   //创建纯在严重逻辑错误,上一个开辟的结点没存任何数据,新开辟的结点和上个结点对指
        L = s;
        else
        s1->next = s;
        s1 = s;
        s->data = a[i];
    }
    s1->next = NULL;
    s = NULL;
    return L;
}
/*
int ListLength(LinkList L)//求表的长度       求表长度多此一举,前面创建就能得到表长
{
    int i=0;
    LinkList p=L->next;
    while(p!=NULL)
    {
        i++;
        p=p->next;
    }
    return i;
}


int GetElem(LinkList *p, int i, int *e)     //得到第i结点元素
{
    int j = 0;
    --i;                              //注意边界值应该为0;
    //LinkList *p;
    //p=L->next;                             你直接指向下一个结点,不考虑第一个?
    if(i < 1||i > 4)
    return 0;
    while(j < i)
    {
        p=p->next;
        j++;
    }
    *e = p->data;                       //p->data是值不是地址
    return (1);
}

int LocateElem(LinkList L, int x)//判断运算         //这些都不给你看了
{
    int i=1;
    struct LNode *p;
    p=L->next;
    while(p!= NULL &&p->data!=x)
    {
        p=p->next;
        i++;
    }
    if(p==NULL)
    return (0);
    else return(i);
}

int ListInsert(LinkList *L, int x, int i)
{
    int j=1;
    LinkList p=L, s;
    s=(LinkList *)malloc(sizeof(LinkList));
    s->data=x;
    s->next=NULL;
    if(i<1||i>ListLength(L)+1)
    return 0;
    while(j<i)
    {
        p= p->next;
        j++;
    }
    s->next=p->next;
    p->next=s;
    return 1;
}
*/
LinkList *Union(LinkList *La, LinkList *Lb)         //集合去重,遍历整个表
{
    LinkList *p, *p1, *p2, *head, *temp;
    head = p = p2 = La;

    while(La != NULL)
    {
      p1 = La;
      La = La->next;
    }
    p1->next = Lb;
    while(p != NULL)
    {
        while(p2 != NULL)
        {

            if(p2->data == p->data && p != p2)
            {
                temp->next = p2->next;
                free(p2);
                p2 = temp->next;
            }
            else
            {
                temp = p2;
                p2 = p2->next;
            }
        }
        p = p->next;
        p2 = p;
    }
    return head;
}


void print(LinkList *p)
{
    while(p != NULL)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

int main(void)
{

    int a[60], b[30];
    int i, e;
    LinkList *headA = NULL;
    LinkList *headB = NULL;

    printf("请输入A:");
    for(i=0; i < 10 ; i++)         //逻辑错误,'\0'只存在字符串,假定链表长度为10好了, 这里也不能直接定结构体数组
    scanf("%d", &a[i]);
    headA = CreateListF(a, 10);
    print(headA);
                //你都直接输入了成员值, 没必要再创建了。你的意图为创建链表

    printf("请输入B:");
    for(i=0; i<5; i++)
    scanf("%d", &b[i]);
    headB = CreateListF(b, 5);
    print(headB);
    //GetElem(headA, 5, &e);       //假设取表A,第5个元素
   
//printf("取到第5个元素为:%d\n", e);
    headA = Union(headA, headB);
    printf("集合A和集合B并集: \n");
    print(headA);
    return 0;

}
#4
九转星河2017-05-25 21:09
一提到查重问题第一反应大都是树型结构或者哈希~笑笑自己还没够火候才会重新联想到常规的线性结构~~
#5
九转星河2017-05-25 21:16
感觉可以先把元素全部单独拿出来然后进行快排或者归并之类的高效排序~然后去重就一目了然了~~
#6
Emotiona2017-05-25 21:20
回复 5楼 九转星河
归并还没去学,快排很有优势。更多的想让题主明白链表怎么回事, 帖子到处都是逻辑错误。。。。。
#7
九转星河2017-05-25 21:27
回复 6楼 Emotiona
归并排序的稳定性比快排要好~不过就是要弄个和排序元素长度相等长度和大小的空间~正常来说申请空间以及释放空间要占用些许运算时间~加上快排函数有标准的qsort型~所以一般情况下快排是相对比较常用的~
#8
cs_逍遥游2017-10-16 20:08
回复 3楼 Emotiona
headA = Union(headA, headB);
你好! 这行代码执行为什么会出现对重载函数调用不明确?
1