算法

47 阅读7分钟

在计算机科学的领域中,数据结构犹如一座神秘的城堡,里面藏着各种各样的奇妙宝藏。

桶排序,就像一个精细的分类机器。以下是桶排序的示例代码:

#include <stdio.h>
int main()
{
    int book[1001],i,j,t,n;
    for(i=0;i<=1000;i++)
        book[i]=0;
    scanf("%d",&n);//输入一个数n,表示接下来有n个数
    for(i=1;i<=n;i++)//循环读入n个数,并进行桶排序
    {
        scanf("%d",&t);  //把每一个数读到变量t中
        book[t]++;  //进行计数,对编号为t的桶放一个小旗子
    }
    for(i=1000;i>=0;i--)  //依次判断编号1000~0的桶
        for(j=1;j<=book[i];j++)  //出现了几次就将桶的编号打印几次
            printf("%d ",i);
    getchar();getchar();
    return 0;
}

冒泡排序,则像是一场优雅的舞蹈。假设有一排高矮不齐的舞者,从最左边开始,两两比较,高的往右移,矮的往左移。以下是冒泡排序的代码示例:

#include <stdio.h>
int main()
{
    int a[100],i,j,t,n;
    scanf("%d",&n);  //输入一个数n,表示接下来有n个数
    for(i=1;i<=n;i++)  //循环读入n个数到数组a中
        scanf("%d",&a[i]);
    //冒泡排序的核心部分
    for(i=1;i<=n-1;i++) //n个数排序,只用进行n-1趟
    {
        for(j=1;j<=n-i;j++) //从第1位开始比较直到最后一个尚未归位的数
        {
            if(a[j]<a[j+1]) //比较大小并交换
            {  t=a[j]; a[j]=a[j+1]; a[j+1]=t;  }
        }
    }
    for(i=1;i<=n;i++)  //输出结果
        printf("%d ",a[i]);
    getchar();getchar();
    return 0;
}

快速排序仿佛是一位智慧的指挥官。面对一群混乱的士兵,先挑选一个基准士兵,然后让小于他的站左边,大于他的站右边。以下是快速排序的代码:

#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left,int right)
{
    int i,j,t,temp;
    if(left>right)
        return;
    temp=a[left]; //temp中存的就是基准数
    i=left;
    j=right;
    while(i!=j)
    {
        //顺序很重要,要先从右往左找
        while(a[j]>=temp && i<j)
            j--;
        //再从左往右找
        while(a[i]<=temp && i<j)
            i++;
        //交换两个数在数组中的位置
        if(i<j)//当哨兵i和哨兵j没有相遇时
        {
            t=a[i];
            a[i]=a[j];
            a[j]=t;
        }
    }
    //最终将基准数归位
    a[left]=a[i];
    a[i]=temp;
    quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程
    quicksort(i+1,right);//继续处理右边的,这里是一个递归的过程
}
int main()
{
    int i,j,t;
    //读入数据
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    quicksort(1,n); //快速排序调用
    //输出排序后的结果
    for(i=1;i<=n;i++)
        printf("%d ",a[i]);
    getchar();getchar();
    return 0;
}

队列,如同银行里的排队系统。人们按照先来后到的顺序排队办理业务,前面的人先处理,后面的人依次等待。以下是队列操作的代码:

#include <stdio.h>
int main()
{
    int q[102]={0,6,3,1,7,5,8,9,2,4},head,tail;
    int i;
    //初始化队列
    head=1;
    tail=10; //队列中已经有9个元素了,tail指向队尾的后一个位置
    while(head<tail) //当队列不为空的时候执行循环
    {
        //打印队首并将队首出队
        printf("%d ",q[head]);
        head++;
        //先将新队首的数添加到队尾
        q[tail]=q[head];
        tail++;
        //再将队首出队
        head++;
    }
    getchar();getchar();
    return 0;
}

栈,恰似一个神奇的魔法筒。先放进去的东西被压在底部,最后才能取出,而最后放进去的却能最先出来。判断回文的栈操作代码如下:

#include <stdio.h>
#include <string.h>
int main()
{
    char a[101],s[101];
    int i,len,mid,next,top;
    gets(a); //读入一行字符串
    len=strlen(a); //求字符串的长度
    mid=len/2-1; //求字符串的中点
    top=0;//栈的初始化
    //将mid前的字符依次入栈
    for(i=0;i<=mid;i++)
        s[++top]=a[i];
    //判断字符串的长度是奇数还是偶数,并找出需要进行字符匹配的起始下标
    if(len%2==0)
        next=mid+1;
    else
        next=mid+2;
    //开始匹配
    for(i=next;i<=len-1;i++)
    {
        if(a[i]!=s[top])
            break;
        top--;
    }
    //如果top的值为0,则说明栈内所有的字符都被一一匹配了
    if(top==0)
        printf("YES");
    else
        printf("NO");
    getchar();getchar();
    return 0;
}

在“小猫钓鱼”的游戏中,队列和栈的结合展现出了精彩的策略对决。代码如下:

#include <stdio.h>
struct queue
{
    int data[1000];
    int head;
    int tail;
};
struct stack
{
    int data[10];
    int top;
};
int main()
{
    struct queue q1,q2;
    struct stack s;
    int book[10];
    int i,t;
    //初始化队列
    q1.head=1; q1.tail=1;
    q2.head=1; q2.tail=1;
    //初始化栈
    s.top=0;
    //初始化用来标记的数组,用来标记哪些牌已经在桌上
    for(i=1;i<=9;i++)
        book[i]=0;
    //依次向队列插入6个数
    //小哼手上的6张牌
    for(i=1;i<=6;i++)
    {
        scanf("%d",&q1.data[q1.tail]);
        q1.tail++;
    }
    //小哈手上的6张牌
    for(i=1;i<=6;i++)
    {
        scanf("%d",&q2.data[q2.tail]);
        q2.tail++;
    }
    while(q1.head<q1.tail && q2.head<q2.tail ) //当队列不为空的时候执行循环
    {
        t=q1.data[q1.head];//小哼出一张牌
        //判断小哼当前打出的牌是否能赢牌
        if(book[t]==0) //表明桌上没有牌面为t的牌
        {
            //小哼此轮没有赢牌
            q1.head++; //小哼已经打出一张牌,所以要把打出的牌出队
            s.top++;
            s.data[s.top]=t; //再把打出的牌放到桌上,即入栈
            book[t]=1; //标记桌上现在已经有牌面为t的牌
        }
        else
        {
            //小哼此轮可以赢牌
            q1.head++;//小哼已经打出一张牌,所以要把打出的牌出队
            q1.data[q1.tail]=t;//紧接着把打出的牌放到手中牌的末尾
            q1.tail++;
            while(s.data[s.top]!=t) //把桌上可以赢得的牌依次放到手中牌的末尾
            {
                book[s.data[s.top]]=0;//取消标记
                q1.data[q1.tail]=s.data[s.top];//依次放入队尾
                q1.tail++;
                s.top--; //栈中少了一张牌,所以栈顶要减1
            }
        }
        t=q2.data[q2.head]; //小哈出一张牌
        //判断小哈当前打出的牌是否能赢牌
        if(book[t]==0) //表明桌上没有牌面为t的牌
        {
            //小哈此轮没有赢牌
            q2.head++; //小哈已经打出一张牌,所以要把打出的牌出队
            s.top++;
            s.data[s.top]=t; //再把打出的牌放到桌上,即入栈
            book[t]=1; //标记桌上现在已经有牌面为t的牌
        }
        else
        {
            //小哈此轮可以赢牌
            q2.head++;//小哈已经打出一张牌,所以要把打出的牌出队
            q2.data[q2.tail]=t;//紧接着把打出的牌放到手中牌的末尾
            q2.tail++;
            while(s.data[s.top]!=t) //把桌上可以赢得的牌依次放到手中牌的末尾
            {
                book[s.data[s.top]]=0;//取消标记
                q2.data[q2.tail]=s.data[s.top];//依次放入队尾
                q2.tail++;
                s.top--;
            }
        }
    }
    if(q2.head==q2.tail)
    {
        printf("小哼win\n");
        printf("小哼当前手中的牌是");
        for(i=q1.head;i<=q1.tail-1;i++)
            printf(" %d",q1.data[i]);
        if(s.top>0) //如果桌上有牌则依次输出桌上的牌
        {
            printf("\n桌上的牌是");
            for(i=1;i<=s.top;i++)
                printf(" %d",s.data[i]);
        }
        else
            printf("\n桌上已经没有牌了");
    }
    else
    {
        printf("小哈win\n");
        printf("小哈当前手中的牌是");
        for(i=q2.head;i<=q2.tail-1;i++)
            printf(" %d",q2.data[i]);
        if(s.top>0) //如果桌上有牌则依次输出桌上的牌
        {
            printf("\n桌上的牌是");
            for(i=1;i<=s.top;i++)
                printf(" %d",s.data[i]);
        }
        else
            printf("\n桌上已经没有牌了");
    }
    getchar();getchar();
    return 0;
}

链表则是灵活多变的精灵。以下是链表操作的示例代码:

#include <stdio.h>
#include <stdlib.h>
//这里创建一个结构体用来表示链表的结点类型
struct node
{
    int data;
    struct node *next;
};
int main()
{
    struct node *head,*p,*q,*t;
    int i,n,a;
    scanf("%d",&n);
    head = NULL;//头指针初始为空
    for(i=1;i<=n;i++)//循环读入n个数
    {
        scanf("%d",&a);
        //动态申请一个空间,用来存放一个结点,并用临时指针p指向这个结点
        p=(struct node *)malloc(sizeof(struct node));
        p->data=a;//将数据存储到当前结点的data域中
        p->next=NULL;//设置当前结点的后继指针指向空,也就是当前结点的下一个结点为空
        if(head==NULL)
            head=p;//如果这是第一个创建的结点,则将头指针指向这个结点
        else
            q->next=p;//如果不是第一个创建的结点,则将上一个结点的后继指针指向当前结点
        q=p;//指针q也指向当前结点
    }
    //输出链表中的所有数
    t=head;
    while(t!=NULL)
    {
        printf("%d ",t->data);
        t=t->next;//继续下一个结点
    }
    getchar();getchar();
    return 0;
}

无论是桶排序的巧妙分类,冒泡排序的逐步交换,快速排序的精准分割,队列的先进先出,栈的后进先出,还是链表的灵活多变,它们共同构成了数据结构丰富多彩的世界,为解决各种复杂的计算机问题提供了强大的工具和方法。