设以带头结点的双向循环链表表示的线性表L=(a1,a2,……,an)。

我的思路是拆开链表,然后先插入奇数位的,再插入偶数位的,要注意链表个数有奇数和偶数两种情况。
我不善于解释,注释都写在代码旁了,function函数就是题目要求的算法,其他函数是用来帮忙构建题目说的链表L的,希望能帮到你。

#include<stdio.h>
#include<malloc.h>
#include<assert.h>
#define Elemtype int
typedef struct DCList
{
    Elemtype data;
    struct DCList *next;
    struct DCList *prior;
}Node;

Node* _buynode(Elemtype x);
void initial(Node **head);
void push_back(Node *head,Elemtype x);
void show(Node *head);
void function(Node *head);

int main()
{
    Node *head;
    initial(&head);

    printf("创建一个双向循环链表(-1结束)\n");
    int x;
    while(1)
    {
        scanf("%d",&x);
        if(x==-1)
        break;
        push_back(head,x);
    }
    printf(">>>");
    show(head);

    printf("function过后的链表\n");
    function(head);
    show(head);

    return(1);
}

Node* _buynode(Elemtype x)
{//本算法的功能是申请一个节点,数据域赋值为x
    //最后返回这个节点的指针
    Node *s=(Node*)malloc(sizeof(Node));
    assert(s!=NULL);

    s->data=x;
    s->next=NULL;
    s->prior=NULL;

    return(s);
}

void initial(Node **head)
{//本算法的功能是初始化一个双向循环链表的头指针
    (*head)=(Node*)malloc(sizeof(Node));
    assert((*head)!=NULL);

    (*head)->data=0;//表长为0
    (*head)->next=(*head)->prior=*head;
}

void push_back(Node *head,Elemtype x)
{//本算法的前提是双向循环链表已经初始化
    //本算法的功能是双向循环链表的尾部插入一个新的节点
    //节点的数据域赋值为x
    Node *last=head->prior;//last指向链表的最后一个节点
    Node *s=_buynode(x);

    s->next=last->next;
    head->prior=s;
    last->next=s;
    s->prior=last;//尾部插入

    head->data++;//表长加一
}

void show(Node *head)
{//本算法的前提是链表至少有一个元素
    //本算法的功能依次显示链表中所有的数据元素
    if(head->data==0)
        return;//表长合法性判断

    Node *p=head->next;
    while(p!=head)
    {
        printf("%d-->",p->data);
        p=p->next;
    }
    printf("head.\n");
}

void function(Node *head)
{//本算法的前提是链表中至少有三个元素
    //本算法是按照一定的规则改造链表
    if(head->data<3)
        return;//表长合法性判断

    Node *p=head->next;
    head->prior->next=NULL;
    p->prior=NULL;
    head->prior=head;
    head->next=head;//拆链表

    Node *s,*s_front,*pa;
    s=p;
    pa=s->next;
    s=pa->next;//保存地址

    p->next=head;
    head->prior=p;
    head->next=p;
    p->prior=head;//尾部插入第一个节点
    pa->prior=NULL;

    while(s!=NULL && s->next!=NULL)//节点偶数个或者奇数个两种情况
    {
        p=s;
        s_front=s->next;
        s=s->next->next;
        p->next->prior=p->prior;
        p->prior->next=p->next;//删除p

        Node *last=head->prior;//last指向head链表尾部节点
        p->next=head;
        head->prior=p;
        last->next=p;
        p->prior=last;//尾部插入节点
    }//将a1,a3,a5...a2n-1插入到链表中

    if(s!=NULL && s->next==NULL)//奇数个情况
    {
        s_front->next=s->next;
        Node *last=head->prior;
        s->next=head;
        head->prior=s;
        last->next=s;
        s->prior=last;//插入尾部
    }

    Node *q=s_front;
    while(s_front!=NULL)//插入剩余a2n,a2n-2...a2节点
    {
        q=q->prior;
        Node *last=head->prior;
        s_front->next=head;
        head->prior=s_front;
        last->next=s_front;
        s_front->prior=last;
        s_front=q;
    }
}

时间复杂度方面,前四句话,也就是第一个while循环前面的代码,时间复杂度是O(1),if语句的时间复杂度也是O(1),两个while循环的时间复杂度分别是O(n/2),加起来就是O(n),所以时间复杂度的要求是满足题意的,这个可以用时间函数去验证。

猜你喜欢

转载自blog.csdn.net/weixin_41133154/article/details/78824204