左神课堂之运用链表解决荷兰国旗问题,要求时间复杂度为o(n),空间复杂度为o(1),还要实现稳定性

荷兰国旗问题描述:
给定一个数n,表示一串数的个数。然后给定一个数number。接着输入n个数,请你设计一个算法,将所有这串数字中比number小的数放在左边,等于number的数放在中间,大于number的数放在右边。
示例:
输入:
5 1
1 5 2 4 0
输出:
0 1 4 2 5

基本思路:构建3个链表,less1,cur,more。less1链表中存放的是所有小于number的数,cur链表中存放的是所有等于number的数,more链表中存放的是所有大于number的数。然后将3个链表拼接起来,输出即可。

操作:第一次先遍历题目给定的链表,找出第一个小于(等于,大于)number的数放入less1(cur,more)链表中去。然后再遍历一遍题目给定的链表,将题目给定的链表中所有小于(等于,大于)number的数按顺序放入less1(cur,more)链表中去,然后将less1,cur,more链表拼接起来,输出即可

代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef struct Node
{
    int value;
    int b;//b是用来判断链表中该节点是否在第一次遍历链表的时候已经放入到了less1(cur,more)链表中去了,如果放进去了,b就为1,否则,b就为0.
    int c;//c是用来判断链表中是否有小于(等于或大于)number的数的,如果没有,c就等于0,如果有,就等于1.
    struct Node *next;
}node,* linkedlist;
int n,z,number;//n表示数字个数,z表示输入的数,number表示number
node *less1,*cur,*more;//less1代表小于number的链表的第一个节点,cur代表等于等于number的链表的第一个节点,more代表大于number的链表的第一个节点
node *endless,*endcur,*endmore;//endless始终指向的是小于number的链表的最后一个节点,endcur始终指向的是等于number的链表的最后一个节点,endmore始终指向的是大于number的链表的最后一个节点
void fuzhi()//给3个链表初始化
{
    less1=(node *)malloc(sizeof(node));//申请空间
    cur=(node *)malloc(sizeof(node));
    more=(node *)malloc(sizeof(node));
    endless=(node *)malloc(sizeof(node));
    endcur=(node *)malloc(sizeof(node));
    endmore=(node *)malloc(sizeof(node));
    less1->next=NULL;cur->next=NULL;more->next=NULL;
}
linkedlist linkedlistcreath()//构建题目给定的链表,尾插法往链表中加入数字
{
    node *l=(node *)malloc(sizeof(node));
    node *r=(node *)malloc(sizeof(node));
    l->next=NULL;
    r=l;
    for(int i=1;i<=n;i++)
    {
        cin>>z;
        node *p=(node *)malloc(sizeof(node));
        p->value=z;
        p->next=r->next;
        p->b=0;
        p->c=0;
        r->next=p;
        r=p;
    }
    return l;//返回的是题目给定的那条链表
}
void ergodiclist(linkedlist l)//第一次遍历题目给定的链表,找出第一个小于(等于,大于)number的数,并放入各自所属的链表中去
{
    node *pre=(node *)malloc(sizeof(node));
    pre=l;
    int cless1=0,ccur=0,cmore=0;//cless1初始为0,如果找出了链表中第一个小于(等于或大于)number的数之后cless1就变为1,如果变为1,以后即使再找到小于(等于或大于)number的数,也不往less1(cur,more)链表中放了
    while (pre->next!=NULL)//遍历链表的固定的格式
    {
        pre=pre->next;
        if(pre->value<number&&!cless1)
        {
            less1->value=pre->value;
            less1->next=NULL;
            pre->b=1;//标记为1,说明这个数是链表中第一个小于number的数
            less1->c=1;//标记为1,说明链表中已经存在了小于number的数了
            cless1=1;
        }
        if(pre->value==number&&!ccur)
        {
             cur->value=pre->value;
             cur->next=NULL;
             pre->b=1;//标记为1,说明这个数是链表中第一个等于number的数
             cur->c=1;//标记为1,说明链表中已经存在了等于number的数了
             ccur=1;
        }
        if(pre->value>number&&!cmore)
        {
             more->value=pre->value;
             more->next=NULL;
             pre->b=1;//标记为1,说明这个数是链表中第一个大于number的数
             more->c=1;//标记为1,说明链表中已经存在了大于number的数了
             cmore=1;
        }
    }
    endless=less1;endcur=cur;endmore=more;//给endless,endcur,endmore赋值(小于(等于,大于)number的链表的最后一个节点)
}
void chongergodiclist(linkedlist l)//重新遍历一遍题目给定的链表,将less1,cur,more链表构建好
{
    node *pre=(node *)malloc(sizeof(node));
    pre=l;
    while (pre->next!=NULL)
    {
        pre=pre->next;
        if(pre->value<number&&pre->b!=1)//条件2如果满足,说明这个节点不是第一个小于number的节点
        {
            node *p=(node *)malloc(sizeof(node));//尾插法构建链表
            p->value=pre->value;
            p->next=NULL;
            endless->next=p;
            endless=p;
        }
        if(pre->value==number&&pre->b!=1)//条件2如果满足,说明这个节点不是第一个等于number的节点
        {
            node *p=(node *)malloc(sizeof(node));//尾插法构建链表
            p->value=pre->value;
            p->next=NULL;
            endcur->next=p;
            endcur=p;
        }
        if(pre->value>number&&pre->b!=1)//条件2如果满足,说明这个节点不是第一个大于number的节点
        {
            node *p=(node *)malloc(sizeof(node));//尾插法构建链表
            p->value=pre->value;
            p->next=NULL;
            endmore->next=p;
            endmore=p;
        }
    }
}
linkedlist connectlist()//将上述构件好的3条链表拼接起来,并用cue来保存。注意:有可能其中一条链表中根本没有数字,这时要仔细扣一下边界
{
     node *cue=(node *)malloc(sizeof(node));
     if(less1->c==1&&cur->c==1&&more->c==1)
     {
         endless->next=cur;
         endcur->next=more;
         cue->next=less1;
     }
     else if(less1->c==1&&cur->c==1&&more->c!=1)
     {
         endless->next=cur;
         cue->next=less1;
     }
     else if(less1->c==1&&cur->c!=1&&more->c==1)
     {
         endless->next=more;
         cue->next=less1;
     }
     else if(less1->c!=1&&cur->c==1&&more->c==1)
     {
         endcur->next=more;
         cue->next=cur;
     }
     else if(less1->c!=1&&cur->c!=1&&more->c==1)
     {
         cue->next=more;
     }
     else if(less1->c==1&&cur->c!=1&&more->c!=1)
     {
         cue->next=less1;
     }
     else if(less1->c!=1&&cur->c==1&&more->c!=1)
     {
         cue->next=cur;
     }
     return cue;
}
void printflinkedlist(linkedlist cue)//打印cue链表
{
    node *pre=(node *)malloc(sizeof(node));
    pre=cue;
    while (pre->next!=NULL)
    {
        pre=pre->next;
        cout<<pre->value<<" ";
    }
}
int main()
{
    cin>>n>>number;
    fuzhi();
    node *l1=(node *)malloc(sizeof(node));//l1链表就相当于题目给定的链表
    l1=linkedlistcreath();//构建链表
    ergodiclist(l1);//第一次遍历
    chongergodiclist(l1);//第二次遍历
    node *cue=(node *)malloc(sizeof(node));
    cue=connectlist();//拼接3条链表
    printflinkedlist(cue);//打印链表
}


猜你喜欢

转载自blog.csdn.net/qq_40938077/article/details/80289756