1052 Linked List Sorting (25分)

题意

给出N个结点的地址address、数据域data以及指针域next,然后给出链表的首地址,要求把在这个链表.上的结点按data值从小到大输出。

样例解释

按照输入,这条链表是这样的(结点格式为[address, data,next]):
[00001, 0, 22222]→[22222, 1000, 12345]→[12345, -1, 33333]→[3333, 100000, 11111]→[1111, 100, -1]

按key值排序之后得到:
[12345, -1, 00001]→[00001, 0, 11111]→[1111, 100, 22222]→[2222, 1000, 33333]→[33333, 100000, -1]

错解

天真的我一开始写了个无比沙雕的代码:

const int N=1e5+10;
struct Node {
    int addr;
    int value;
    int nxt;

    bool operator<(const Node &W) const
    {
        return value < W.value;
    }
}a[N];
int n,head;

int main()
{
    cin>>n>>head;

    for(int i=0;i<n;i++) cin>>a[i].addr>>a[i].value>>a[i].nxt;

    sort(a,a+n);

    printf("%d %05d\n",n,a[0].addr);

    for(int i=0;i<n;i++)
    {
        if(i == n-1)
            printf("%05d %d -1",a[i].addr,a[i].value);
        else
            printf("%05d %d %05d\n",a[i].addr,a[i].value,a[i+1].addr);
    }

    //system("pause");
    return 0;
}

完全没有考虑不在链表上的结点,直接对所有结点一窝蜂排序,就这还能骗\(21\)分,?_?。

正解

  1. 定义静态链表,其中结点性质由bool型变量flag定义,表示为结点在链表中是否出现。flag 为false表示无效结点(不在链表上的结点)。
  2. 初始化,令flag均为false(即0),表示初始状态下所有结点都是无效结点。
  3. 由题目给出的链表首地址begin遍历整条链表,并标记有效结点的flag为true(即1),同时计数有效结点的个数count。
  4. 对结点进行排序,排序函数cmp的排序原则是;如果cmp的两个参数结点中有无效结点的话,则按flag从大到小排序,以把有效结点排到数组左端( 因为有效结点的flag为1,大于无效结点的flag);否则按数据域从小到大排序。
  5. 由于有效结点已经按照数据域从小到大排序,因此按要求输出有效结点即可。
const int N=1e5+10;
struct Node {
    int addr,val,nxt;
    bool exist;

    bool operator<(const Node &W) const
    {
        if(exist == false || W.exist == false)
            return exist > W.exist;
        else
            return val < W.val;
    }
}a[N];
int n,head;

int main()
{
    cin>>n>>head;

    for(int i=0;i<n;i++)
    {
        int addr,val,nxt;
        cin>>addr>>val>>nxt;
        a[addr]={addr,val,nxt};
    }

    int p=head;
    int cnt=0;
    while(p != -1)
    {
        cnt++;
        a[p].exist = true;
        p = a[p].nxt;
    }

    if(cnt == 0)
    {
        printf("%d %d\n",cnt,head);
    }
    else
    {
        sort(a,a+N);
        
        printf("%d %05d\n",cnt,a[0].addr);
        
        for(int i=0;i<cnt;i++)
            if(i == cnt-1)
                printf("%05d %d -1",a[i].addr,a[i].val);
            else
                printf("%05d %d %05d\n",a[i].addr,a[i].val,a[i+1].addr);
    }
    //system("pause");
    return 0;
}

用vector记录所有在链表上的结点也可,效率更高(相比对所有元素排序而言,这里只对有效的结点进行排序),注意对\(0\)的特判。

const int N=1e5+10;
struct Node {
    int addr,val,nxt;
    
    bool operator<(const Node &W) const
    {
        return val < W.val;
    }
}a[N];
int n,head;

int main()
{
    cin>>n>>head;

    for(int i=0;i<n;i++)
    {
        int addr,val,nxt;
        cin>>addr>>val>>nxt;
        a[addr]={addr,val,nxt};
    }

    int p=head;
    vector<Node> v;
    while(p != -1)
    {
        v.pb(a[p]);
        p = a[p].nxt;
    }

    sort(v.begin(),v.end());
    
    if(v.size() == 0)
    {
        printf("%d %d\n",v.size(),head);
    }
    else
    {
        printf("%d %05d\n",v.size(),v[0].addr);
    
        for(int i=0;i<v.size();i++)
            if(i == v.size()-1)
                printf("%05d %d -1",v[i].addr,v[i].val);
            else
                printf("%05d %d %05d\n",v[i].addr,v[i].val,v[i+1].addr);
    }
    //system("pause");
    return 0;
}
posted @ 2021-01-31 21:04  Dazzling!  阅读(67)  评论(0编辑  收藏  举报