zoukankan      html  css  js  c++  java
  • PAT线性结构_一元多项式求导、按给定步长反转链表、出栈序列存在性判断

    02-线性结构1. 一元多项式求导 (25)
    设计函数求一元多项式的导数。(注:xn(n为整数)的一阶导数为n*xn-1。)
    
    输入格式:以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
    
    输出格式:以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是0,但是表示为“0 0”。
    
    输入样例:
    3 4 -5 2 6 1 -2 0
    输出样例:
    12 3 -10 1 6 0
    

    最简单的方式是用数组模拟,但是毕竟处在学习数据结构阶段,所以还是写了个链表的,如下:

    #include<stdio.h>
    #include<malloc.h>
    typedef struct Node
    {
        int coef; // 系数
        int exp; // 指数
        struct Node * next;
    }NODE, *PNODE;
    int main(void)
    {
        int coef, exp;
        PNODE pHead, pTail, pTemp;
        
        pHead = (PNODE)malloc(sizeof(NODE)); // 创建头节点
        pTail = pHead;
        
        while(scanf("%d%d", &coef, &exp) != EOF)
        {
            pTemp = (PNODE)malloc(sizeof(NODE));
            pTemp->coef = coef;
            pTemp->exp = exp; // 注: 因为有尾指针,所以省略了next设为NULL这一步
            pTail->next = pTemp; 
            pTail = pTemp;
        }
        pTail->next = NULL; 
        // 扫描、求值并输出
        pTemp = pHead->next; // 定位到首元素
        if(pTemp->exp == 0) // 首元素指数为零,其求导比较特殊因此单独处理
        {
            printf("0 0"); 
        }
        else
        {
            while(pTemp)
            {
                if(pTemp->exp > 0) // 指数为零的项求导直接为零,不进行输出
                {
                    if(pTemp != pHead->next) //如果不是第一个元素输出空格
                        putchar(' ');
                    printf("%d %d", pTemp->coef * pTemp->exp, pTemp->exp -1);
                
                    pTemp = pTemp->next;
                }
                
                else 
                    break;
            }
        }    
        // 注:申请内存没有判断是否成功,内存用完了也没释放,懒le:~
        return 0;
    }
    02-线性结构2. Reversing Linked List (25)
    时间限制
    Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K = 3, then you must output 3→2→1→6→5→4; if K = 4, you must output 4→3→2→1→5→6.
    
    Input Specification:
    
    Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (<= 105) which is the total number of nodes, and a positive K (<=N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
    
    Then N lines follow, each describes a node in the format:
    
    Address Data Next
    
    where Address is the position of the node, Data is an integer, and Next is the position of the next node.
    
    Output Specification:
    
    For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.
    
    Sample Input:
    00100 6 4
    00000 4 99999
    00100 1 12309
    68237 6 -1
    33218 3 00000
    99999 5 68237
    12309 2 33218
    Sample Output:
    00000 4 33218
    33218 3 12309
    12309 2 00100
    00100 1 99999
    99999 5 68237
    68237 6 -1
    

    我投机取巧,用了数组模拟,当然也可以用三指针法:

    #include<stdio.h> // 大数组模拟
    #define MAXN 100000
    typedef struct Node
    {
        int address;
        int data;
        int next;
    }NODE, *PNODE;
    NODE node[MAXN+10];
    void Swap(NODE node[], int, int);
    void Swap2(NODE node[], int, int);
    void Reverse(NODE node[], int, int);
    int main(void)
    {
        int firstAddress, n, k; // 首地址、节点个数、反转长度
        int i, j, address;
        
        scanf("%d%d%d", &firstAddress, &n, &k);
        for(i = 1; i <= n; i++)
        {
            scanf("%d%d%d", &node[i].address, &node[i].data, &node[i].next);
            if(node[i].address == firstAddress)
                j = i;
                
        }
        // 交换第一个元素与应当排在首位的元素,如果多次使用的话应该编写一个函数,传递适当的参数给它完成数据的交换
        Swap(node, 1, j);
        // 首先根据节点地址信息进行排序
        for(i = 2; i <= n; i++)
        {
            address = node[i-1].next;
            if(address == -1) 
            {
                n = i - 1; // 修改n的值达到排除输入数据中无效节点的目的
                break;
            }
            
            for(j = i; j <= n; j++)
                if(address == node[j].address)
                {
                    Swap(node, i, j);
    
                    break;
                }
        }
        // printf("n: %d
    ", n); // test
        Reverse(node, n, k);
        
        for(i = 1; i < n; i++)
            printf("%05d %d %05d
    ", node[i].address, node[i].data, node[i].next); // 0n表示宽度至少为n位,不足以左边0填充
        printf("%05d %d %d
    ", node[i].address, node[i].data, node[i].next);
        
        return 0;
    }
    
    void Swap(NODE node[], int i, int j)
    {
        int temp;
        
        temp = node[i].address;
        node[i].address = node[j].address;
        node[j].address = temp;
        
        temp = node[i].data;
        node[i].data = node[j].data;
        node[j].data = temp;
        
        temp = node[i].next;
        node[i].next = node[j].next;
        node[j].next = temp;
    }
    
    void Swap2(NODE node[], int i, int j) // 作为反转操作的一个子函数来使用,注意与Swap函数的不同点,即它不关心next变量
    {
        int temp;
        
        temp = node[i].address;
        node[i].address = node[j].address;
        node[j].address = temp;
        
        temp = node[i].data;
        node[i].data = node[j].data;
        node[j].data = temp;
    }
    
    void Reverse(NODE node[], int n, int k)
    {
        int i, j, step;
        int totalReverNum = n / k;
        
        for(i = 1; i <= totalReverNum; i++)
        {
            step = 0;
            for(j = 0; j < k/2; j++)
            {
                Swap2(node, (k*(i-1)+1)+step, k*i-step); // 如果想提速,可以把乘法在调用Swap2之前算出来,但是这样会增加变量的个数,权衡之下如果不超时的话就不做修改了:~
                step++;
            }    
        }
        
        //遍历,修改next
        for(i = 1; i < n; i++)
        {
            node[i].next = node[i+1].address;
        }
        node[i].next = -1;
    }

    下面给出经典的利用三个指针变量进行反转的思路:

    Ptr Reverse(Ptr head, int K) // head是一个无用的头节点
    {
        cnt = 1;
        new = head->next;
        old = new->next;
        while(cnt < K)
        {
            tmp = old->next;
            old->next = new;
            new = old;
            old = tmp;
            cnt++;
        }
        head->next->next = old;
        return new;
    }
    02-线性结构3. Pop Sequence (25)
    Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, ..., N and pop randomly. You are supposed to tell if a given sequence of numbers is a possible pop sequence of the stack. For example, if M is 5 and N is 7, we can obtain 1, 2, 3, 4, 5, 6, 7 from the stack, but not 3, 2, 1, 7, 5, 6, 4.
    
    Input Specification:
    
    Each input file contains one test case. For each case, the first line contains 3 numbers (all no more than 1000): M (the maximum capacity of the stack), N (the length of push sequence), and K (the number of pop sequences to be checked). Then K lines follow, each contains a pop sequence of N numbers. All the numbers in a line are separated by a space.
    
    Output Specification:
    
    For each pop sequence, print in one line "YES" if it is indeed a possible pop sequence of the stack, or "NO" if not.
    
    Sample Input:
    5 7 5
    1 2 3 4 5 6 7
    3 2 1 7 5 6 4
    7 6 5 4 3 2 1
    5 6 4 3 7 2 1
    1 7 6 5 4 3 2
    Sample Output:
    YES
    NO
    NO
    YES
    NO
    
    // 这个题还是有些难度的,类比于火车进站的问题,需要考虑的点比较多,感觉本质上还是一道模拟题。
    #include<stdio.h>
    #define MAXN 1000
    int stack[MAXN+10];
    int arr[MAXN+10]; 
    int main(void)
    {
        int m, n, k, i, j;
        int x, y, top; // x模拟进栈序列,y模拟出栈序列,top代表栈顶
        
        scanf("%d%d%d", &m, &n, &k);
        
        for(i = 1; i <= k; i++)
        {
            for(j = 1; j <= n; j++)
                scanf("%d", &arr[j]);
                
            y = 1;
            top = 0;
            for(x = 1; x <= n; x++) // n个数字逐个入栈
            {    
                stack[++top] = x;
                if(top > m)
                    break;
                
                while(top > 0 && arr[y] == stack[top])
                {
                    y++;
                    top--;
                }        
            }
            
            if(x <= n || top > 0)
                printf("NO
    ");
            else
                printf("YES
    ");
        }
        
        
        return 0;
    }

    上面是数组模拟的,下面我写了一个真实版的栈模拟:

    #include<stdio.h>
    #include<malloc.h>
    typedef struct Node
    {
        int data;
        struct Node * next;
    }NODE, *PNODE;
    
    typedef struct Stack
    {
        PNODE pHead;
        int sumItem;
    }STACK, *PSTACK;
    
    void MakeStack(PSTACK pS);
    int IsEmpty(PSTACK pS);
    void Push(PSTACK pS, int value);
    int Pop(PSTACK pS);
    int Peek(PSTACK pS);
    int SumItem(PSTACK pS);
    void Clear(PSTACK pS);
    
    int arr[1010];
    int main(void)
    {    
        int m, n, k, i, j;
        int x, y; // x模拟进栈序列,arr[y]模拟出栈序列
        STACK S;
            
        scanf("%d%d%d", &m, &n, &k);
        
            
        MakeStack(&S);
        for(i = 1; i <= k; i++)
        {
            for(j = 1; j <= n; j++)
                scanf("%d", &arr[j]);
                
            y = 1; 
            Clear(&S);
            for(x = 1; x <= n; x++) // n个数字逐个入栈
            {    
                Push(&S, x);
                if(SumItem(&S) > m)
                    break;
                
                while(!IsEmpty(&S) && arr[y] == Peek(&S))
                {
                    // printf("haha, I am here.
    "); // test
                    y++;
                    Pop(&S);
                }        
            }
            
            if(x <= n || !IsEmpty(&S))
                printf("NO
    ");
            else
                printf("YES
    ");
        }
        
        
        
        return 0;
    }
    
    void MakeStack(PSTACK pS)
    {
        pS->pHead = NULL;
        pS->sumItem = 0;
    }
    
    int IsEmpty(PSTACK pS)
    {
        if(pS->pHead == NULL)
            return 1;
        else
            return 0;
    }
    
    void Push(PSTACK pS, int value)
    {
        PNODE pTemp;
        
        pTemp = pS->pHead;
        pS->pHead = (PNODE)malloc(sizeof(NODE));
        pS->pHead->data = value;
        pS->pHead->next = pTemp;
        pS->sumItem++;    
    }
    
    int Pop(PSTACK pS) // 调用前需要调用IsEmpty来判断栈是否为空,在主程序中的短路原则体现了这一点,因此Pop函数中省略了判空这一步
    {
        int value;
        PNODE pTemp;
    
        value = pS->pHead->data;
        pTemp = pS->pHead;
        pS->pHead = pS->pHead->next;
        pS->sumItem--;
        free(pTemp);
        return value;
    }
    
    int Peek(PSTACK pS) // 调用前需要调用IsEmpty来判断栈是否为空,没有判空的原因同上
    {
        return pS->pHead->data;
    }
    
    int SumItem(PSTACK pS)
    {
        return pS->sumItem;
    }
    
    void Clear(PSTACK pS)
    {
        while(!IsEmpty(pS))
            Pop(pS);
    }

    (END_XPJIANG)

  • 相关阅读:
    vue之前端鉴权
    vue jsx与render的区别及基本使用
    vue-svgicon基本使用
    vue-cli 3.0按需引入element-ui
    手动实现Promise
    checkbox、radio设置自定义样式
    AngularJS之拖拽排序(ngDraggable.js)
    webpack 4.x之搭建前端开发环境
    VUE,基于vue-cli搭建创建vue项目
    ES6面向对象 动态添加标签页
  • 原文地址:https://www.cnblogs.com/xpjiang/p/4567265.html
Copyright © 2011-2022 走看看