zoukankan      html  css  js  c++  java
  • 02-线性结构3 Reversing Linked List

      这是我到目前为止这个习题集中花时间最久ac的题目了……其实一开始思路还是挺清晰的,但是有三个测试点很长时间通过不了,最终结合别人的方法对自己的代码进行了大改。

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #define MaxSize 100001
      4 
      5 typedef struct LNode *List;
      6 struct LNode{
      7     int Addr;
      8     int Data;
      9     int NextAddr;
     10     List Next;
     11 };
     12 
     13 List FormList(int FirstAdd, int N, int *pn)
     14 {
     15 //    struct LNode LN[MaxSize];
     16     List head;
     17     int tmpAddr;  //as the index of the original array
     18     int i;
     19     int Addr[MaxSize], Data[MaxSize], NextAddr[MaxSize];
     20     struct LNode LN[N + 1];
     21     LN[0].NextAddr = FirstAdd;
     22     for(i = 0; i < N; i++){
     23         scanf("%d", &tmpAddr);
     24         scanf("%d %d", &Data[tmpAddr], &NextAddr[tmpAddr]);
     25     }
     26     i = 1;
     27     while(1){
     28         if(LN[i - 1].NextAddr == -1){
     29             LN[i - 1].Next = NULL;
     30             (*pn) = i - 1;
     31             break;
     32         }
     33         LN[i].Addr = LN[i - 1].NextAddr;
     34         LN[i].Data = Data[LN[i].Addr];
     35         LN[i].NextAddr = NextAddr[LN[i].Addr];
     36         LN[i - 1].Next = LN + i;  //?
     37         i++;
     38     }
     39     head = LN;
     40     return head;
     41 }
     42 
     43 void PrintList(List L)
     44 {
     45     List p;
     46     p = L;
     47     while(p->Next){
     48         p = p->Next;
     49         if(p->NextAddr == -1)
     50             printf("%05d %d %d
    ", p->Addr, p->Data, p->NextAddr);
     51         else
     52             printf("%05d %d %05d
    ",p->Addr, p->Data, p->NextAddr );
     53     }
     54 }
     55 
     56 List Reverse(List head, int K)
     57 {
     58     int cnt = 1;
     59     List newP, old, tmp;
     60     newP = head->Next;
     61     old = newP->Next;
     62     while(cnt < K){
     63         tmp = old->Next;
     64         old->Next = newP;
     65         old->NextAddr = newP->Addr;
     66         newP = old;
     67         old = tmp;
     68         cnt++;
     69     }
     70     head->Next->Next = old;
     71     if(old)
     72         head->Next->NextAddr = old->Addr;
     73     else
     74         head->Next->NextAddr = -1;
     75     return newP;
     76 }
     77 
     78 int main(int argc, char const *argv[])
     79 {
     80     int FirstAdd, N, K;
     81     int i, j;
     82     int num = 0;
     83     int *pn = &num;
     84     List L;
     85     scanf("%d %d %d", &FirstAdd, &N, &K);
     86     L = FormList(FirstAdd, N, pn);
     87     List p, rp;
     88     p = L;
     89     rp = NULL;
     90     if(K <= num){
     91         for(i = 0; i < (num/K); i++){
     92             rp = Reverse(p, K);
     93             p->Next = rp;  //更新p
     94             p->NextAddr = rp->Addr;  //NextAddr的变换尤为重要
     95             for(j = 0; j < K; j++)
     96                 p = p->Next;
     97         }
     98     }
     99     PrintList(L);
    100     return 0;
    101 }

      测试点“正好全反转”对应90 - 98行,当num是K的整数倍时,链表要每段都整体反转多次。

      测试点“有多余结点不在链表上”对应num参数的操作,num代表输入的有效结点的个数,当输入一些链外结点时它们不会被计入有效结点,以保证循环次数的正确。

      测试点“最大N,最后剩下K - 1不反转”除了需要考虑num数值以保证反转数的正确,还涉及了对时间复杂度的考察。这也是我最后一个通过的测试点,因为起先我的思路是把每组输入的内容都以结点形式存储下来:

    List FormList(int FirstAdd, int N, int *pn)
    {
        List L[MaxSize], head, tmp;
        int i, j;
        int Addr[MaxSize], Data[MaxSize], NextAddr[MaxSize];
        L[0] = (List)malloc(sizeof(struct LNode));
        //L[0] as the head node,
        //whose Data and Addr is null while Next points to the first valid node
        for(i = 1; i < N + 1; i++)
            scanf("%d %d %d", &Addr[i], &Data[i], &NextAddr[i]);
        for(i = 1; i < N + 1; i++){
            if(Addr[i] == FirstAdd){
                L[1] = (List)malloc(sizeof(struct LNode));
                L[1]->Addr = Addr[i];
                L[1]->Data = Data[i];
                L[1]->NextAddr = NextAddr[i];
                L[0]->Next = L[1];  //Now the first valid node was constructed and pointed by the head node
                (*pn)++; 
                break;
            }
        }
        i = 1;
        while(1){
            for(j = 1; j < N + 1; j++){
                if(L[i]->NextAddr == Addr[j]){
                    (*pn)++;
                    L[i + 1] = (List)malloc(sizeof(struct LNode));
                    L[i + 1]->Addr = Addr[j];
                    L[i + 1]->Data = Data[j];
                    L[i + 1]->NextAddr = NextAddr[j];
                    L[i]->Next = L[i + 1];
                }
            }
            if(L[i]->NextAddr == -1){
                L[i]->Next = NULL;
                break;
            }
            i++;
        }
        head = L[0];
        free(L[0]);
        return head;
    }

      这样虽然很明确对应了每个独立结点,也方便串联操作,但是构建时的时间复杂度已达到O(n2),测试最大N时会超时,所以后来还是改用了数组方法,这才提升了操作效率。

  • 相关阅读:
    谈谈焦虑
    Bridge
    Abstract Factory
    开篇辞
    缓存穿透和缓存雪崩
    缓存与数据库的一致性思考
    GDB
    代码格式化
    CSMA/CA协议
    18年秋招(19届)复习指导+面经总结,手把手教你进大厂——阿里、网易、京东、多益等
  • 原文地址:https://www.cnblogs.com/biankun/p/8648760.html
Copyright © 2011-2022 走看看