| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1126 人关注过本帖
标题:几种排序方法的动态特征(TC图形模式表述)
取消只看楼主 加入收藏
hoodlum1980
Rank: 2
来 自:浙江大学
等 级:论坛游民
威 望:2
帖 子:289
专家分:23
注 册:2008-2-24
收藏
 问题点数:0 回复次数:0 
几种排序方法的动态特征(TC图形模式表述)
------------------------------------------
声明:本帖的主体内容和思想不属于我的原创。在我看《C算法》(Algorithms In C Third Edition, 作者:Robert Sedgewick)的电子书时,看到排序的时候作者用了这样的图来描述动态特征,我觉得非常有趣。因此在这里我采用TC绘图方式实现描述排序的动态特征,可以看到不同排序方法中的排序过程。
------------------------------------------
    在这里示范了选择,插入,冒泡,摇摆,希尔,快速等基本排序的动态特征,除了ShakedBubble属于课后习题是我自己写的以外,其他排序代码基本原样引用该书第一卷第6章中的代码。有时间再补充其他排序方法。下面给出的是用散点表示的代码,排序前为随机散落的点,排序以后会点会落到对角线上。在附件中还包含用柱状线表示的动态排序过程(动态柱线的代码类似,因此省略)。

程序代码:
/*
    演示基本排序的动态特征图形
    code by hoodlum1980
    2008年10月9日
*/
#include <stdio.h>
#include <graphics.h>
#include <stdlib.h> /* random() */
#include <dos.h> /* delay() */
#include <time.h> /* clock() */

typedef void (*SORTFUNC)(int [], int, int); /*定义排序方法的指针*/

/*排序元素的数量*/
#define NMAX         1000
/*要排序的数组*/
int a[NMAX];

/*矩形边界坐标*/
#define BLEFT         150
#define BTOP             50
#define BWIDTH         200
#define BHEIGHT     200
#define BBOTTOM     (BTOP+BHEIGHT)
#define BRIGHT        (BLEFT+BWIDTH)

/*把数组索引换算为横坐标,把被排序元素的值换算为纵坐标*/
#define GET_X(pindex)    (int)(BLEFT + BWIDTH*1.0/NMAX*(pindex))
#define GET_Y(pvalue)    (int)(BTOP + BHEIGHT*1.0/NMAX*(NMAX-1-(pvalue)))

/*初始化数组,根据type分别初始化为随机,有序,逆序*/
/*type= 0: random; 1: ascent , 2: descent */
void InitArray(int a[], int length, int type)
{
    int i;
    setcolor(WHITE);
    setfillstyle(SOLID_FILL, BLACK);
    bar(BLEFT-1,BTOP-1,BLEFT+BWIDTH+1, BTOP+BHEIGHT+1);
    rectangle(BLEFT-1,BTOP-1,BLEFT+BWIDTH+1,BTOP+BHEIGHT+1);
    rectangle(BLEFT-12,BTOP-12,BLEFT+BWIDTH+12, BTOP+BHEIGHT+12);
    setfillstyle(SOLID_FILL, DARKGRAY);
    floodfill(BLEFT-5, BTOP-5, getcolor());
    for(i=0;i<length;i++)
    {
        switch(type)
        {
            case 1: a[i]=i; break;
            case 2: a[i]=length-1-i;break;
            default: a[i]=random(length); break;
        }
        putpixel(GET_X(i),GET_Y(a[i]),YELLOW);
    }
}

/*在矩形的下方,显示一个字符串信息*/
void DisplayText(char* text)
{
    setcolor(WHITE);
    setfillstyle(SOLID_FILL, BLACK);
    bar(BLEFT-1,BTOP+BHEIGHT+20,BLEFT+BWIDTH+200, BTOP+BHEIGHT+60);
    outtextxy(BLEFT+2, BTOP+BHEIGHT+22, text);
}

/*改变数组a某个位置的值*/
void ChangeValue(int a[], int index, int newValue)
{
    putpixel(GET_X(index), GET_Y(a[index]), BLACK);
    a[index]=newValue;
    putpixel(GET_X(index), GET_Y(a[index]), YELLOW);
}

/*交换两个元素*/
void exch(int a[], int t1, int t2)
{
    int temp;
    temp=a[t1];
    ChangeValue(a, t1, a[t2]);    /*a[t1]=a[t2];*/
    ChangeValue(a, t2, temp);        /*a[t2]=temp;*/
}

/*比较并在必要时交换,让 第二项 >= 第一项*/
void compexch(int a[], int t1, int t2)
{
    if(a[t1]>a[t2])
        exch(a, t1, t2);
}

/*选择排序:(移动数据次数最少的排序方法)
  代码引用自:<<C算法(第一卷 基础、数据结构、排序和搜索)(第三版)>>

 */
void Selection(int a[], int left, int right)
{
    int i,j,min;
    for(i=left; i<right; i++)
    {
        min=i;
        for(j=i+1; j<=right; j++)
            if(a[j]<a[min]) min=j;
        exch(a, i, min);
    }
}

/*插入排序:效率低,但代码简洁一些

 */
void InsertionSlow(int a[], int left, int right)
{
    int i, j;
    for(i=left+1;i<=right;i++)
        for(j=i;j>left;j--)
            compexch(a, j-1, j);
}

/*插入排序:是对InsertionSlow的改进和提速
  代码引用自:<<C算法(第一卷 基础、数据结构、排序和搜索)(第三版)>>

 */
void Insertion(int a[], int left, int right)
{
    int i, j, temp;
    for(i=left+1; i<=right; i++)/*扫描一遍,把最小值放在第一个位置*/
        compexch(a, left, i);
    for(i=left+2; i<=right; i++)
    {
        j=i;
        temp=a[i];/*缓存待插入值*/
        while(temp<a[j-1]) /*找出要插入的位置j*/
        {
            ChangeValue(a, j, a[j-1]); /*a[j]=a[j-1]; 大于插入值的数据整体向后移动*/
            j--;
        }
        ChangeValue(a, j, temp); /*插入该值*/
    }
}

/*希尔排序:改进插入排序数据移动距离长而缓慢的缺点
  代码引用自:<<C算法(第一卷 基础、数据结构、排序和搜索)(第三版)>>

 */
void ShellSort(int a[], int left, int right)
{
    int i, j, h, temp;/*h为间隔*/
    /*求出h初始间隔*/
    for(h=1; h<=(right-1)/9; h=3*h+1);
    /*对h的递减序列进行 h间隔插入排序*/
    for(; h>0; h/=3)
    {
        for(i=left+h; i<=right; i++)
        {
            j=i;
            temp=a[i];
            while(j >= left+h && temp<a[j-h])
            {
                ChangeValue(a, j, a[j-h]); /*a[j]=a[j-h];*/
                j-=h;
            }
            ChangeValue(a, j, temp); /*a[j]=temp;*/
        }
    }
}

/*冒泡排序:
  代码引用自:<<C算法(第一卷 基础、数据结构、排序和搜索)(第三版)>>

 */
void Bubble(int a[], int left, int right)
{
    int i, j;
    for(i=left;i<right;i++)
        for(j=right;j>i;j--)
            compexch(a, j-1, j);
}

/*摇摆式冒泡排序:扫描方向交替,但貌似并不比普通冒泡快

 */
void ShakedBubble(int a[], int left, int right)
{
    int j;
    /*摇摆式扫描!交替上浮下沉,未排序区间左右摇摆,逐渐缩小到到中点*/
    while(left<right)
    {
        /*选一个最小的下沉*/
        for(j=right;j>left;j--)
            compexch(a, j-1, j);
        left++;

        /*选一个最大的上浮*/
        for(j=left+1;j<=right;j++)
            compexch(a, j-1, j);
        right--;
    }
}

/*快速排序的划分函数,QSort会调用该函数进行划分*/
int Partition(int a[],int left,int right)
{
    int i=left,j=right+1;
    int key=a[left],temp;    /*缓存最左边元素的值,以该值划分!*/
    while(1)
    {
        while(a[++i]<key && i<right);
        while(a[--j]>key);
        /*如果i和j相遇,说明扫描一次结束*/
        if(i>=j)
            break;
        exch(a,i,j);/* swap(a[i],a[j] */
    }
    /*swap(a[left],a[j]*/
    ChangeValue(a, left, a[j]);    /*a[left]=a[j];*/ /*把key所在位置的元素放到最左端的key的位置*/
    ChangeValue(a, j, key);            /*a[j]=key;*/            /*把key移动到正确的位置,即它最终在有序列中的位置*/
    return j;
}

/*快速排序*/
void QSort(int a[],int left,int right)
{
    int p, i, key;
    if(left<right)/*回归条件*/
    {
        key=a[left];
        p=Partition(a,left,right);
        QSort(a,left,p-1);    /*左半段排序*/
        QSort(a,p+1,right); /*右半段排序*/
    }
}

void main()
{
    int             gdriver=DETECT, gmode, i, j;
    clock_t     timebase, time[10][3];
    char            text[128];
    char*            orders[] = {"random  ",    "asc     ", "desc    "}; /*被排序数组的类型*/
    char*         names[] =    
        {
            "InsertionSlow", "Insertion    ", "ShellSort    ",    "Bubble       ", 
            "ShakedBubble ", "Selection    ",    "QSort        "
        };
    SORTFUNC     funcs[]={InsertionSlow, Insertion, ShellSort, Bubble, ShakedBubble, Selection, QSort };

    initgraph(&gdriver,&gmode,"");
    for(i=0; i< sizeof(funcs)/sizeof(funcs[0]);i++)
    {
        for(j=0; j<3; j++) /*做不同的初始化*/
        {
            sprintf(text, "%s-%s", names[i], orders[j]);
            DisplayText(text);
            InitArray(a, NMAX, j);
            timebase=clock();
            (funcs[i])(a, 0, NMAX-1);
            time[i][j]=clock()-timebase;
            getch();
        }
    }
    closegraph();

    /*输出计时时间*/
    printf(" ------------------------------------------ \n");
    printf("                |  random      asc     desc \n");
    printf(" ------------------------------------------ \n");
    for(i=0; i< sizeof(funcs)/sizeof(funcs[0]);i++)
    {
        printf("  %s |", names[i]);
        for(j=0; j<3; j++) printf("%8ld ", time[i][j]);
        printf("\n ------------------------------------------ \n");
    }
    getch();
}


[[it] 本帖最后由 hoodlum1980 于 2008-10-11 15:00 编辑 [/it]]

Sort_JFD.rar (96.91 KB) 可执行文件和代码



bubble.jpg (26.14 KB)
图片附件: 游客没有浏览图片的权限,请 登录注册


sort_jfd2.jpg (24.3 KB)
图片附件: 游客没有浏览图片的权限,请 登录注册
搜索更多相关主题的帖子: 动态 特征 冒泡 代码 
2008-10-09 05:21
快速回复:几种排序方法的动态特征(TC图形模式表述)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.028009 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved