【数据结构初学笔记06】第二章MOOC课后习题PAT

编程作业实战:

1. 两个有序链表序列的合并 这是一道C语言函数填空题,训练最基本的链表操作。如果会用C编程的话,一定要做;

2. 一元多项式的乘法与加法运算 在“小白专场”里,我们会详细讨论C语言实现的方法。对于不会C语言而不能做第1题的同学,本题一定要做

3.  Reversing Linked List 根据某大公司笔试题改编的2014年春季PAT真题,不难,可以尝试;

4.  Pop Sequence  是2013年PAT春季考试真题,考察队堆栈的基本概念的掌握,应可以一试。

01.两个有序链表序列的合并

List Merge(List L1, List L2)
{
    List P, prear, temp;
    P = (List)malloc(sizeof(struct Node));
    P->Next = NULL;
    prear = P; //链表的末尾
    while (L1->Next && L2->Next)
    {
        if (L1->Next->Data < L2->Next->Data) //若L1数据>L2数据,将该节点连接到结果链表P上,并使L1继续指向该节点的下一节点
        {
            temp = L1->Next;
            L1->Next = temp->Next;
            prear->Next = temp;
            prear = temp;
        }
        else if (L1->Next->Data > L2->Next->Data) //若L1数据<L2数据,情况同上,对L2进行操作。
        {
            temp = L2->Next;
            L2->Next = temp->Next;
            prear->Next = temp;
            prear = temp;
        }
        else //若L1数据=L2数据,同时对L1和L2进行操作
        {
            temp = L1->Next;
            L1->Next = temp->Next;
            prear->Next = temp;
            prear = temp;
            temp = L2->Next;
            L2->Next = temp->Next;
            prear->Next = temp;
            prear = temp;
        }
    }
    //将L1或L2的剩余部分全部连接到结果末尾
    while (L1->Next)
    {
        temp = L1->Next;
        L1->Next = temp->Next;
        prear->Next = temp;
        prear = temp;
    }
    while (L2->Next)
    {
        temp = L2->Next;
        L2->Next = temp->Next;
        prear->Next = temp;
        prear = temp;
    }
    return P;
}

02.一元多项式的乘法与加法运算

//设计函数分别求两个一元多项式的乘积与和
//已知两个多项式:(1) 3x4 - 5x2 + 6x - 2,(2) 5x20 - 7x4 + 3x;
//多项式和:5x20 - 4x4- 5x2 + 9x - 2
//多项式乘积:15x24-25x22+30x21-10x20-21x8+35x6-33x5+14x4-15x3+18x2-6x

/*设计思路*/
// 1多项式表示:采用链表进行设计,每个节点包含:系数值coef,指数值expon,下一节点指针
// 2程序框架:读入多项式1和2,加法运算并输出,乘法运算并输出
// 3读入多项式:创建新节点,存入信息,并连接到已有节点后,返回头节点指针。这里创建的是不带头节点的线性表。
// 4两个多项式相加:创建结果头节点,依次判断两个多项式指数是否相同。输入和输出均为不带头结点的线性表,
//   若相同则相加结果不为零时创建节点连接到已有多项式后,若不同将高次项连接到结果多项式,继续比较,
//   当有一多项式链表指向空时停止比较,将零一多项式剩余部分连接到结果多项式后,并返回结果多项式链表的头节点指针。
// 5两个多项式的乘法1:将P1的每一项与P2相乘,并加入结果多项式中;
//   对于P1一项与P2相乘的每一步,要先申请空间存入相乘结果,并将结果与输出结果P相加,再释放掉P2的空间。
// 6两个多项式的乘法2:逐项插入,将P1第i项与P2第j项相乘,并插入到结果多项式。对于初始结果多项式,可由P1第1项与P2相乘得到。
//  插入时,需要考虑结果多项式是否为空;若不为空,需要判断插入位置,末尾,中间或前面,注意释放空间;
//  若插入中间,需要判断是否存在指数相等的项;若存在指数相等的项,需要判断是否会导致该项系数为零

#include <stdio.h>
#include <stdlib.h>
typedef struct PolyNode *Polynomial;
struct PolyNode
{
    int coef;              //系数
    int expon;             //指数
    struct PolyNode *link; //指向下一个节点的指针
};

Polynomial PolyRead();                                   //读入多项式
Polynomial Mult1(Polynomial P1, Polynomial P2);          //乘法1实现
Polynomial Mult2(Polynomial P1, Polynomial P2);          //乘法2实现
Polynomial PolyAdd(Polynomial P1, Polynomial P2);        //加法实现
void PrintPoly(Polynomial P);                            //显示多项式
void Attach(int coef, int expon, Polynomial *prear);     //连接
int compare(int e1, int e2);                             //比较
Polynomial CopyPoly(Polynomial P1);                      //复制多项式
void InsertNode(int coef, int expon, Polynomial *prear); //将结果项插入到结果多项式合适位置
int main(void)
{
    Polynomial P1, P2, PP2, PS;
    P1 = PolyRead();
    P2 = PolyRead();
    if(P1==NULL)
    {
        printf("0 0\n");
        PrintPoly(P2);
        return 0;
    }
    else if(P2==NULL)
    {
        printf("0 0\n");
        PrintPoly(P1);
        return 0;
    }
    // printf("乘法1>>>\n");
    // PP1 = Mult1(P1, P2); //按照方法1相乘的结果
    // printf("乘法2>>>\n");
    PP2 = Mult2(P1, P2); //按照方法2相乘的结果
    // printf("运算结果>>>\n");
    // printf("乘法一运算结果:");
    // PrintPoly(PP1);
    // printf("乘法二运算结果:");
    PrintPoly(PP2);
    PS = PolyAdd(P1, P2);
    // printf("加法运算结果:");
    PrintPoly(PS);
    // while (1);
    return 0;
}
Polynomial PolyRead()
{
    int N, c, e;
    Polynomial rear, temp, P;
    P = (Polynomial)malloc(sizeof(struct PolyNode));
    rear = P;
    scanf("%d", &N);
    if (N == 0)
    {
        P->link = NULL;
    }
    else
    while (N--)
    {
        scanf("%d %d", &c, &e);
        Attach(c, e, &rear);
        // temp = (Polynomial)malloc(sizeof(struct PolyNode));
        // temp->expon = e;
        // temp->coef = c;
        // temp->link = NULL;
        // PP->link = temp;
        // PP = temp;
    }
    temp = P;
    P = P->link;
    free(temp);
    //这里最好输出一下,进行一下检查
    // printf("输入多项式:");
    // PrintPoly(P);
    return P;
}
Polynomial PolyAdd(Polynomial P1, Polynomial P2)
{
    Polynomial front, rear, temp;
    int sum;
    rear = (Polynomial)malloc(sizeof(struct PolyNode)); //定义了一个临时空节点,作为结果多项式的表头
    front = rear;
    while (P1 && P2) //判断指针是否为空指针,空指针表示多项式结束
    {
        switch (compare(P1->expon, P2->expon))
        {
        case 1: // P1中的数据项指数大
            Attach(P1->coef, P1->expon, &rear);
            P1 = P1->link;
            break;
        case -1: // P2中的数据项指数大
            Attach(P2->coef, P2->expon, &rear);
            P2 = P2->link;
            break;
        case 0: //数据项指相同
            sum = P1->coef + P2->coef;
            if (sum) //判断系数和是否为零
                Attach(sum, P1->expon, &rear);
            P1 = P1->link;
            P2 = P2->link;
            break;
        }
    }
    /*将未处理完的另一个多项式的所有节点依次连接到结果多项式中*/
    for (; P1; P1 = P1->link)
        Attach(P1->coef, P1->expon, &rear);
    for (; P2; P2 = P2->link)
        Attach(P2->coef, P2->expon, &rear);
    rear->link = NULL;
    temp = front;
    front = front->link;
    free(temp); //释放空白头节点的空间
    return front;
}
void Attach(int coef, int expon, Polynomial *prear)
{ //这里prear是一个指针变量,传递的是PolyAdd函数中结果多项式尾节点指针变量rear的地址
    //函数功能:将新节点添加到(*prear)节点后
    Polynomial P;
    P = (Polynomial)malloc(sizeof(struct PolyNode)); //创建新节点用于存储结果的系数和指数值,函数结束该内存不会被回收。
    P->coef = coef;
    P->expon = expon;
    P->link = NULL;
    (*prear)->link = P;
    *prear = P; //使尾节点指针变量指向新节点
}
int compare(int e1, int e2)
{
    if (e1 == e2)
        return 0;
    if (e1 > e2)
        return 1;
    if (e1 < e2)
        return -1;
}
// Polynomial Mult1(Polynomial P1, Polynomial P2)
// {
//     Polynomial P, prear, P0, t1, t2;
//     t1 = P1;

//     int i = 1;
//     P0 = (Polynomial)malloc(sizeof(struct PolyNode)); //创建一个空节点,存放P1第i项与P2相乘的结果
//     P0->link = NULL;
//     while (P1)
//     {
//         t2 = P2;
//         P0 = (Polynomial)malloc(sizeof(struct PolyNode)); //创建一个空节点,存放P1第i项与P2相乘的结果
//         P0->link = NULL;
//         prear = P0; //存放计算的临时结果,每次计算产生的临时结果链表空间一定是一样长的。
//         while (t2)
//         {
//             Attach(P1->coef * t2->coef, P1->expon + t2->expon, &prear); //多项式系数一定不为0
//             t2 = t2->link;
//         }
//         printf("P1_%d * P2=",i);
//         PrintPoly(P0->link);
//         if (i == 1) //第一次运算,直接将临时结果P0的值赋给P
//         {
//             P = CopyPoly(P0->link);
//         }
//         else //不是第一次运算,可以使用多项式相加函数,注意临时结果P0的头节点为空
//         {
//             P = PolyAdd(P, P0->link);
//         }
//         P1 = P1->link;
//         i++;
//         while (P0) //释放掉临时结果的链表空间,每次计算产生的临时结果链表空间一定是一样长的。
//         {
//             Polynomial temp;
//             temp = P0;
//             P0 = P0->link;
//             free(temp);
//         }
//     }
//     return P;
// }
Polynomial Mult2(Polynomial P1, Polynomial P2)
{
    Polynomial t1, t2, P, prear, temp;
    int coef, expon, i, j;
    t1 = P1;
    t2 = P2;
    P = (Polynomial)malloc(sizeof(struct PolyNode)); //创建一个空节点,存放计算结果。
    P->link = NULL;
    prear = P; //表示P的尾节点
    while (t2)
    {
        Attach(P1->coef * t2->coef, P1->expon + t2->expon, &prear); //多项式系数一定不为0
        t2 = t2->link;
    }
    t1 = t1->link;
    // printf("P1_1 * P2=");
    // PrintPoly(P->link);
    i = 2;
    while (t1)
    {
        t2 = P2;
        j = 1;
        while (t2)
        {
            coef = t1->coef * t2->coef;
            expon = t1->expon + t2->expon;
            InsertNode(coef, expon, &P); //将结果项插入到结果多项式中
            t2 = t2->link;
            // printf("P1_%d * P2_%d=%dX^%d,结果多项式:", i, j, coef, expon);
            // PrintPoly(P->link);
            j++;
        }
        i++;
        t1 = t1->link;
    }
    temp = P;
    P = P->link;
    free(temp);
    return P;
}
void PrintPoly(Polynomial P)
{
    if (!P)
    {
        printf("0 0");
        return;
    }
    while (P)
    {
        printf("%d %d", P->coef, P->expon);
        P = P->link;
        if (P)
            printf(" ");
    }
    printf("\n");
    return;
}
Polynomial CopyPoly(Polynomial P0)
{
    Polynomial P, temp;
    P = (Polynomial)malloc(sizeof(struct PolyNode));
    temp = P;
    while (P0)
    {
        Attach(P0->coef, P0->expon, &temp);
        P0 = P0->link;
    }
    temp = P;
    P = P->link;
    free(temp);
    return P;
}
void InsertNode(int coef, int expon, Polynomial *prear)
{ //将结果项插入到结果多项式合适位置
    Polynomial temp1, temp2, NewNode;
    int sum;
    temp1 = (*prear)->link;
    if (!temp1) //结果多项式为空
    {
        // printf("临时结果多项式为空,插入前:");
        // PrintPoly(temp1);
        temp1 = NewNode;
        temp1->coef = coef;
        temp1->expon = expon;
        temp1->link = NULL;
        // printf("插入后:");
        // PrintPoly(temp1);
    }
    else //结果多项式不为空
    {
        NewNode = (Polynomial)malloc(sizeof(struct PolyNode));
        NewNode->coef = coef;
        NewNode->expon = expon;
        while (temp1 && temp1->expon > expon) //若结果多项式非空,筛选出temp2>NewNode>=temp1
        {
            temp2 = temp1;
            temp1 = temp1->link;
        }
        if (temp1 == NULL) //情况1:插入在结果末尾
        {
            temp2->link = NewNode;
            NewNode->link = NULL;
        }
        else if (temp1->expon == expon) //情况2:存在一项temp1,指数相同
        {
            sum = temp1->coef + coef;
            if (sum) //指数相同,且和不为零
            {
                temp1->coef = sum;
                free(NewNode);
            }
            else //指数相同,且和为零
            {
                temp2->link = temp1->link;
                free(temp1);
                free(NewNode);
            }
        }
        else //情况3:指数在temp2和temp1之间
        {
            temp2->link = NewNode;
            NewNode->link = temp1;
        }
    }
}

03.Reversing Linked List

#include <stdio.h>
#include <stdlib.h>
#define NULL -1
#define MaxSize 100000
// typedef struct ListNode *LNode;
struct ListNode
{
    int Address;
    int Data;
    int NextAddress;
} L[MaxSize]; //定义一个数组链表
int main(void)
{
    //输入链表
    int i, j, FirstAdd, N, K, Knum;
    scanf("%d%d%d", &FirstAdd, &N, &K);
    for (i = 0; i < N; i++)
    {
        scanf("%d%d%d", &L[i].Address, &L[i].Data, &L[i].NextAddress);
    }
    L[N].Address = NULL;
    //按照所输入的数据地址对链表进行排序
    struct ListNode t1, t2; //
    for (i = 0; i < N; i++)
    {
        for (j = i; j < N; j++)
        {
            if (L[j].Address == FirstAdd)
            {
                FirstAdd = L[j].NextAddress;
                t1 = L[i];
                L[i] = L[j];
                L[j] = t1;
                break;
            }
        }
        if (FirstAdd == NULL) //判断是否到链表结尾,已排除有多余结点不在链表上的情况
        {
            N = i + 1;
        }
    }
    //按照K个间隔进行倒序处理
    Knum = N / K;
    // printf("%d", Knum);
    for (i = 0; i < Knum; i++)
    {
        for (j = 0; j < (K / 2); j++)
        {
            t1 = L[i * K + j];
            L[i * K + j] = L[i * K + K - j - 1];
            L[i * K + K - j - 1] = t1;
        }
    }
    //更新前N-1个结点的NextAddress值,并输出
    for (i = 0; i < N - 1; i++)
    {
        L[i].NextAddress = L[i + 1].Address;
        printf("%05d %d %05d\n", L[i].Address, L[i].Data, L[i].NextAddress);
    }
    L[i].NextAddress = -1; //更新最后一个结点的NextAddress值
    printf("%05d %d %d\n", L[i].Address, L[i].Data, L[i].NextAddress);
    return 0;
}

04.Pop Sequence

//检查方法:数123...i,输入序列L;
//如果堆栈为空,向堆栈Push一个数i;
//比较堆栈顶元素和L[j]的大小:相等,则堆栈Pop,j++;如果不相等,(检查堆栈是否满),Push数i,i++
//如果堆栈已满,而L还未到末尾值,输出NO;如果堆栈未满,继续Push,若外面没有剩余的i,输出NO;
//如果L末尾值与堆栈栈顶元素匹配,即i==j,输出YES

#include <stdio.h>
#include <stdlib.h>
#define ElementType int
typedef struct SNode *Stack;
struct SNode
{
    ElementType Data, NodeNum;
    Stack Next;
};
Stack CreateSnack();
int IsEmpty(Stack S);
void Push(Stack S, ElementType t);
ElementType Pop(Stack S);
int main(void)
{
    Stack S;
    S = CreateSnack();
    ElementType StackSize, Length, Num, i, j, k, w;
    scanf("%d %d %d", &StackSize, &Length, &Num);
    S->NodeNum = 0;
    int L[Num][Length], Result[Num];
    for (k = 0; k < Num; k++)
    {
        for (i = 0; i < Length; i++) //输入一行数据,存入数组L[];
            scanf("%d", &L[k][i]);
    }

    for (k = 0; k < Num; k++)
    {
        w = 0; //数组L[k][w]
        i = 1; //顺序数123...Length
        while(!IsEmpty(S))
        {
            Pop(S);
        }
        while (1)
        {
            if (IsEmpty(S))
            {
                if (i <= Length)
                {
                    // printf("空堆栈,Push操作");
                    Push(S, i);
                    i++;
                }
            }
            //比较栈顶元素与序列数L[i]
            if (S->Next->Data == L[k][w]) //相等,堆栈Pop,j++
            {
                Pop(S);
                w++;
            }
            else //不相等,(检查堆栈满没满),继续Push
            {
                if (S->NodeNum == StackSize)
                {
                    Result[k] = 0;
                    break;
                    ;
                }
                else
                {
                    Push(S, i);
                    i++;
                }
            }
            //判断是否到达数123的末尾
            if (i > Length + 1) //数123已经全部送进堆栈,NO
            {
                Result[k] = 0;
                break;
                ;
            }
            if (i == Length + 1 && w == Length) //数123和L[k]匹配,YES
            {
                Result[k] = 1;
                break;
            }
        }
    }
    //输出判断结果
    for (i = 0; i < Num; i++)
    {
        if (Result[i])
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}
Stack CreateSnack()
{ //创建空堆栈,带头结点形式,返回堆栈头节点地址
    Stack S;
    S = (Stack)malloc(sizeof(struct SNode));
    S->Next = NULL;
    return S;
}
int IsEmpty(Stack S)
{ //判断堆栈是否为空,空返回1,非空返回0
    if (S->Next == NULL)
        return 1;
    else
        return 0;
}
void Push(Stack S, ElementType t)
{ //入栈
    Stack temp;
    temp = (Stack)malloc(sizeof(struct SNode));
    temp->Data = t;
    temp->Next = S->Next;
    S->Next = temp;
    S->NodeNum++;
}
ElementType Pop(Stack S)
{ //出栈
    Stack FirstCell;
    ElementType TopElem;
    if (S->Next == NULL)
    {
        printf("堆栈空");
        return -1;
    }
    else
    {
        FirstCell = S->Next;
        S->Next = FirstCell->Next;
        TopElem = FirstCell->Data;
        free(FirstCell);
        S->NodeNum--;
        return TopElem;
    }
}

结束

课程来源:浙江大学数据结构慕课MOOC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值