zoukankan      html  css  js  c++  java
  • 集合的操作

    问题描述 :

    输入A、B、C、D四个集合(集合中无重复元素,且元素值都大于0),分别存储在不带头结点的链表中。

    本程序先将四个集合执行以下操作:

    1. 对A、B、C、D分别进行升序排序;(该功能已实现,见函数sort)。

    2. 做A=A+B操作:先执行两个有序链表A和B的合并,并仍然保持有序,结果存储在A中,然后删除重复元素;(该功能已实现,见函数merge和purge)。

    3. 做A=A-C操作:将C中出现的元素从A中删除;(该功能已实现,见函数subtract)。

    4. 对D中出现的元素,逐一到A中查询:

      1. 如果在A中存在,则从A中删除

      2. 如果在A中不存在,则将元素添加到A中,并保持链表A有序。

    请编写函数fun的函数体实现本功能。

    5. 输出集合A中的元素。(该功能已实现,见函数displayLink)。

    需要编写的函数的原型如下:

    struct student* fun(struct student* L1, struct student* L2)

    形参:

    L1:传入的第一个集合,程序中将传入A集合的链表头指针

    L2:传入的第二个集合,程序中将传入D集合的链表头指针

    返回值:

    返回第一个集合的链表的头指针

    首先输入一行,包含一个整数N,表示共测试N组数据。

    后面接着输入4*N行,每行为一个集合的元素。

    每组数据的第1行为集合A的元素,第2行为集合B的元素,第3行为集合C的元素,第4行为集合D的元素。

    每个集合的元素值都为大于0的整数,输入时,-1表示结束。

    输出说明 :

     输出的信息以head开头,以tail结尾,以“-->”分隔。如果是空链表,则直接输出“head-->tail”。具体见输出范例。

    输入范例 :

    2
    3 5 8 10 15 9 -1
    2 5 8 11 14 -1
    2 5 10 -1
    3 1 9 -1
    3 5 8 10 15 9 -1
    2 5 8 11 14 -1
    2 5 10 -1
    2 3 8 -1

    输出范例 :

    head-->1-->8-->11-->14-->15-->tail
    head-->2-->9-->11-->14-->15-->tail

    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    using namespace std;
    struct student
    {
        int  num;
        struct student* next;
    };
    struct student* createByTail()
    {
        struct student* head;
        struct student* p1, * p2;
        int n;
        n = 0;
        p1 = p2 = (struct student*)malloc(sizeof(struct student));
        scanf("%d", &p1->num);
        head = NULL;  //首先置链表为空链表
        while (p1->num != -1)    //num为-1,意味着用户输入结束
        {
            n = n + 1;
            if (n == 1)            //创建第一个结点
                head = p1;
            else
                p2->next = p1;
            p2 = p1;            //p2始终指向最后一个结点(即尾指针)
            p1 = (struct student*)malloc(sizeof(struct student)); //p1指向新结点
            scanf("%d", &p1->num);
        }
        p2->next = NULL;  //切记:最后一个结点的next赋值为NULL
        return head;
    }
    //输出链表中的信息(num)
    void  displayLink(struct student* head)
    {
        struct student* p;
        p = head;
        printf("head-->");
        while (p != NULL)
        {
            printf("%d-->", p->num);
            p = p->next;
        }
        printf("tail
    ");
    }
    struct student* insertNodeInOrder(struct student* head, struct student* stu)
    {
        struct student* p0, * p1, * p2=NULL;
        p1 = head;
        p0 = stu;
        if (head == NULL) //目前还是空链表
        {
            p0->next = head;
            head = p0;
        }
        else
        {
            while ((p0->num > p1->num) && (p1->next != NULL))
            {//查找插入位置,p2指向p1的前驱
                p2 = p1;
                p1 = p1->next;
            }
            //while循环的结束条件有两个,下面需要判断是由哪个条件退出循环
            if (p0->num <= p1->num)
            {//由while循环条件的第一个条件退出循环,因此可插在p1结点之前
                if (head == p1)     head = p0;
                else   p2->next = p0;
                p0->next = p1;
            }
            else
            {//由while循环条件的第二个条件退出循环,因此p0->num最大,要插在最后
                p1->next = p0;
                p0->next = NULL;
            }
        }
        return head;
    }
    struct student* sort(struct student* head)
    {
        struct student* p, * s;
        p = head;
        head = NULL;
        while (p)
        {
            s = p;
            p = p->next;
            head = insertNodeInOrder(head, s);
        }
        return head;
    }
    struct student* merge(struct student* LA, struct student* LB)
    {
        struct student* p, * s;
        p = LB;
        while (p)
        {
            s = p;
            p = p->next;
            LA = insertNodeInOrder(LA, s);
        }
        return LA;
    }
    struct student* subtract(struct student* LA, struct student* LB)
    {
        struct student* q, * p = LB;
        struct student* pre = NULL;//pre指向q的前驱,所以最开始赋为NULL
        while (p != NULL) //对LB链表遍历
        {
            q = LA;
            while (q != NULL && q->num != p->num)
            {
                pre = q;
                q = q->next; //在LA中查找是否有元素与p->num相同
            }
            if (q != NULL) //找到了相同的元素,则删除q所指向结点
            {
                if (q == LA) //如果删除第一个结点
                {
                    LA = LA->next;
                    free(q);
                }
                else
                {
                    pre->next = q->next;
                    free(q);
                }
            }
            p = p->next;
        }
        return LA;
    }
    //删除重复元素
    void purge(struct student* head)
    {
        struct student* p, * q;
        if (head == NULL || head->next == NULL)
            return;
        p = head;
        while (p->next != NULL)
        {
            if (p->num == p->next->num)
            {
                q = p->next;
                p->next = q->next;
                free(q);
            }
            else
            {
                p = p->next;
            }
        }
    }
    /*对D中出现的元素,逐一到A中查询:
    如果在A中存在,则从A中删除
    如果在A中不存在,则将元素添加到A中,并保持链表A有序。*/
    struct student* fun(struct student* L1, struct student* L2)
    {
        /*******************************编写本函数************************************/
        struct student* pl2 = L2,*pl1,*q,*pl1_pre;
        while (pl2)//循环L2
        {
            pl1_pre = NULL;
            pl1 = L1;
            while (pl1 && pl1->num < pl2->num)
            {
                pl1_pre = pl1;
                pl1 = pl1->next;
            }
            if (!pl1||(pl2->num != pl1->num))//这里意思是不存在该元素
            {
                q= (struct student*)malloc(sizeof(struct student)); //p1指向新结点 
                q->num = pl2->num;
                L1 = insertNodeInOrder(L1, q);
            }
            else//存在该元素pl1指向该元素
            {
                if (pl1 == L1)//若是头
                {
                    q = pl1;
                    L1 = pl1->next;
                    free(q);
                }
                else//不是头
                {
                    q = pl1;
                    pl1_pre->next = pl1->next;
                    free(q);
                }
            }
            pl2 = pl2->next;
        }
        return L1;
    }
    int main()
    {
        struct student* headA, * headB, * headC, * headD;
        int i = 0, n;
        scanf("%d", &n);
        while (i < n)
        {
            headA = createByTail();//创建链表A
            headB = createByTail();//创建链表B
            headC = createByTail();//创建链表C
            headD = createByTail();//创建链表D
            headA = sort(headA);//链表A排序
            headB = sort(headB);//链表B排序
            headC = sort(headC);//链表C排序
            headD = sort(headD);//链表D排序
    
            headA = merge(headA, headB);//将链表B合并到链表A中
            purge(headA);//删除链表A中重复元素
            headA = subtract(headA, headC);//从链表A中减去链表C中元素
            headA = fun(headA, headD);//对链表A和链表D调用fun函数
            displayLink(headA);//输出链表A中的元素
            i++;
        }
        return 0;
    }
  • 相关阅读:
    ORACLE中seq$表更新频繁的分析
    VmWare平台Windows Server 2012 无响应宕机
    SQL Challenge ——快速找到1-100之间缺失的数
    ORACLE推导参数Derived Parameter介绍
    SQL SERVER 数据库各版本功能对比
    Jsp中格式化时间戳的常用标签
    SQL Server 2014 Database Mail重复发送邮件特殊案例
    采用HTML5之“data
    多线程之策略模式
    docker attach卡住,和exec的选择
  • 原文地址:https://www.cnblogs.com/lancelee98/p/13190579.html
Copyright © 2011-2022 走看看