循环双链表的一个应用和与数组的比较

链表是数据结构中常见的一种,使用也很频繁 。但大多时候可以使用链表则也可以使用数组 下面在一个例子中分别使用数组和链表来对比下两者的区别和各自的特点.
题目:小球 从左到右一次编号为 1,2,3,4,5…n 可以执行两种指令 A x y 或者B x y
A x y 为将x 编号的球放到y编号的球的左边
B x y 为将x编号的球放到y编号的球的右边
最后输出整个球的经过调整后的顺序
输入:6 2
A 2 4
B 3 6
输出:1 2 4 5 6 3
输入:6 为球的个数 2 为操作的次数
A 2 4 和B 3 6为两次操作 分别将2放到4的左边 3 放到6的右边
输出 为最后的球的顺序.
下面我将用数组和循环双链表来模拟这种操作

下面是使用数组来模拟的代码

#include <stdio.h>
#include <stdlib.h>
int find(int* data,int x,int n)//在data数组里找到x 并返回他的下标
{
    int i=1;
    for(;i<=n;i++)
        if(data[i]==x)
        return i;
}
void shift_right(int start,int end,int *data)//在data数组里从start开始到end结束全部向右边移动一位
{
    int i=end;
    for(;i>=start;i--)
        data[i+1]=data[i];

}
void shift_left(int start,int end,int *data)//在data数组里从start开始到end结束全部向左边移动一位
{
    int i=start;
    for(;i<=end;i++)
        data[i-1]=data[i];
}
int main()
{
    int n,m,i;
    int *data;
    scanf("%d%d",&n,&m);//n为球的个数 m为操作的次数
    data=(int *)malloc((n+1)*sizeof(int));//申请内存空间
    for(i=1;i<=n;i++)//模拟n个小球的情况
        data[i]=i;
    for(i=1;i<=m;i++)
    {
        char type[10];
        int x,y,p,q,temp;
        scanf("%s%d%d",type,&x,&y);//输入移动类型和两个小球的数字
        p=find(data,x,n);
        q=find(data,y,n);
        if(type[0]=='A')//将x放在y左边
        {
            if(p>q)
            {
                temp=data[p];
                shift_right(q,p-1,data);//移动数组
                data[q]=temp;
            }
            else
            {
                temp=data[p];
                shift_left(p+1,q-1,data);//移动数组
                data[q-1]=temp;

            }
        }
        else//将x放在y右边
        {
            if(p>q)
            {
                temp=data[p];
                shift_right(q+1,p-1,data);//移动数组
                data[q+1]=temp;
            }
            else
            {
                temp=data[p];
                shift_left(p+1,q,data);//移动数组
                data[q]=temp;
            }
        }
    }
    for(i=1;i<=n;i++)
        printf("%d ",data[i]);
}

下面是使用循环双链表来模拟的代码

#include <stdio.h>
#include <stdlib.h>
typedef struct linknode{
    struct linknode *left;
    struct linknode *right;
    int data;

}LinkNode;
void Link(LinkNode *x,LinkNode *y)//将y放到x 的右边
{
    x->right=y;
    y->left=x;
}
LinkNode *Find(int x,LinkNode *p)
{
    while(p->data!=x)
        p=p->right;
    return p;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    LinkNode*p=(LinkNode*)malloc(sizeof(LinkNode));
    int i=1;
    LinkNode *pre=p,*now;//前驱指针初始化
    p->data=0;
    for(;i<=n;i++)//创建链表
    {
        now=(LinkNode*)malloc(sizeof(LinkNode));
        now->data=i;
        Link(pre,now);
        pre=now;
    }
    Link(now,p);//形成环型双链表
    char type[10];
    int x,y;
    for(i=1;i<=m;i++)
    {
        scanf("%s%d%d",type,&x,&y);
        LinkNode *xpointer,*ypointer;
        xpointer=Find(x,p);//找到x
        ypointer=Find(y,p);//找到y
        xpointer->left->right=xpointer->right;
        xpointer->right->left=xpointer->left;//删除x
        if(type[0]=='A')//x在y的左边
        {
            Link(ypointer->left,xpointer);
            Link(xpointer,ypointer);
        }
        else//x在y的右边
        {
            Link(xpointer,ypointer->right);
            Link(ypointer,xpointer);
        }
    }
    now=p->right;
    while(now!=p)
    {
        printf("%d ",now->data);
        now=now->right;
    }


}

下面来分析下两者的区别和各自的优点
利用数组来模拟的话则需要不停的来移动数组的元素 例如6个球 编号为1 2 3 4 5 6如果我要将2放在6的右边则我必须
把3 4 5 6都向左边移动一位然后再将2插到6原来的位子上 利:实现简单 弊:如果元素过多则会有很多的元素移动会大大降低运行速度
利用链表来模拟上次的这个过程的话则要先将2从循环双链表中删除然后再将其插入6的右边 。利:代码的执行速度会大大的提高 弊 :实现可能比用数组的话复杂了一点

你可能感兴趣的:(数据结构,链表,数组,应用)