你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 编程语言
2.13 C#实现选择法排序的动态演示程序
 

一、引言

排序是计算机数据处理中的一项重要操作,通过排序可以提高查找的效率。在一般情况下,排序问题的输入是输入n个数a1a2a3……an的一个序列,要设计一个有效的排序算法,产生输入序列的一个重新排列:a11 a21 a31……an1,使得a11< a21< a31<……< an1。输入序列通常是一个有n个元素的数组。随着近十年来数据处理规模的迅速增长,计算机用于处理排序所花的总时间越来越多,熟练的掌握一些典型的排序算法,对于程序设计人员来说是非常重要的。

二、选择法排序


初始序列:     9    0    5    3    7    8     4    2     10    1

第一遍排序: 0  9    5    3    7    8     4    2     10    1

第二遍排序: 0    1  5    3    7    8     4    2     10    9

第三遍排序: 0    1    2  3    7    8     4    5     10    9

第四遍排序: 0    1    2    3  7    8     4    5     10    9

第五遍排序: 0    1    2    3    4  8     7    5     10    9

第六遍排序: 0    1    2    3    4    5   7    8     10    9

第七遍排序: 0    1    2    3    4    5     7  8     10    9

第八遍排序: 0    1    2    3    4    5     7    8   10    9

第九遍排序: 0    1    2    3    4    5     7    8     9   10

排序结果:   0    1    2    3    4    5     7    8     9     10

1:选择法排序具体示例


假设要处理的数据存放在数组A[]中。选择法排序的基本思想是:对待排序的数组序列进行n-1遍的处理,第i遍处理是将A[i]A[i+1]……A[n]中值最小者与A[i]交换位置。这样,经过i遍处理后,前i个数据的位置就已经是正确的了。下面通过一个具体的实例来理解选择排序的排序过程。

从上述选择法排序的基本思想及排序过程可以看出,要实现选择法排序,共需要两层循环:第一层循环用来控制排序需要进行几遍,第二层循环用于控制在第i遍排序时在未排序的数据中查找值最小的,用来和待定位置上的数据进行交换。实现选择法排序的算法描述如下:

void SelectSort(int[] a)

{   //共需要.a.Length - 1遍循环,a.Length为元素个数

    for (int i = 0; i < a.Length - 1; i++) 

    {  //i指示下一个最小的数据待确定的位置

        int k = i;                 //k用来记录剩余元素中值最小的位置 

        for (int j = i; j < a.Length; j++)

        { //在未排序的数据中查找值最小的数据的位置,并记录在变量k

            if (a[j] < a[k])

                k = j;

        }

        if (k != i)  //如果第i个数据不是最小的,则和最小的进行交换

        {   int temp = a[i];

            a[i] = a[k];

            a[k] = temp;

        }

    }

}

三、动态演示程序

在窗体的界面上放置一个面板控件Panel,作为展示动态排序过程的窗口,在窗体上设置两个定时器控件Timer,一个用来控制排序的外层循环,另一个用来控制排序的内层循环,即用两个Timer控件实现上面算法中的两层循环,从而达到动态显示排序过程的目的,设置两个Timer控件的Interval属性的值可以控制排序的速度。程序中的关键代码如下:

1、在类中定义如下变量:

private const int MAXNUMBERS = 60;//数组最大元素个数

private int[] numbers;            //存放数据的数组

//动态显示排序过程的Label控件数组

private System.Windows.Forms.Label[] lblNumbers = new Label[MAXNUMBERS];

private int iOuter;  //控制外层循环

private int jInner;  //控制内层循环

private int k;       //记录最小数据的位置

2、生成初始界面和数据由窗体上的命令按钮“生成数据”完成,其实现代码如下:

private void btnCreateNumber_Click(object sender, EventArgs e)

{

    btnClear_Click(null, null);//清除面板中的标签

    this.txtResult.Clear();    //清除文本框的内容

    iOuter = 0;                //设置新一次排序

    Random random = new Random();//获取数据个数

    int nDataNumbers = int.Parse(this.num_DataNumbers.Value.ToString());

    numbers = new int[nDataNumbers];

    for (int i = 0, k = 0, j = 0; i < nDataNumbers; i++, k++)

    {

        if (i % 9 == i / 9)

        {

            k = 0;

            j = i % 9;

        }

        //随机产生数据

        int temp = -256 + random.Next(512);

        numbers[i] = temp;

        //在面板中安排标签并设置标签的相关属性

        lblNumbers[i] = new Label();

        lblNumbers[i].Location = new Point(k * 50 + 20, j * 50 + 20);

        lblNumbers[i].Size = new Size(40, 30);

        lblNumbers[i].BackColor = Color.Red;

        lblNumbers[i].ForeColor = Color.Yellow;

        lblNumbers[i].Text = temp.ToString();

        lblNumbers[i].Font = new Font("宋体", 12);

        lblNumbers[i].TextAlign = ContentAlignment.MiddleCenter;

        this.panNumber.Controls.Add(lblNumbers[i]);

    }

    string rr = "";

    for (int jj = 0; jj <= numbers.Length - 2; jj++)

    {

        rr = rr + numbers[jj].ToString() + " ";

    }

    rr = rr + numbers[numbers.Length - 1].ToString();

    txtResult.Text = "初始数据序列:" + rr;

}

3、使用Timer控件tmrOuter控制排序的外层循环的实现,具体实现代码如下:

private void tmrOuter_Tick(object sender, EventArgs e)

{

    if (iOuter < numbers.Length - 1)

    {   //每趟排序时假设初始的数据为最小值,设置当前最小值颜色

        lblNumbers[iOuter].ForeColor = Color.Red;

        lblNumbers[iOuter].BackColor = Color.Yellow;

        k = iOuter;

        jInner = iOuter + 1;

        //设置搜索标签的颜色

        lblNumbers[jInner].ForeColor = Color.Blue;

        lblNumbers[jInner].BackColor = SystemColors.Control;

 

        tmrOuter.Enabled = false;

        tmrInner.Enabled = true;

    }

    else    //排序结束处理

    {

        lblNumbers[iOuter].ForeColor = Color.Black;

        lblNumbers[iOuter].BackColor = SystemColors.Control;

       

        tmrOuter.Enabled = false;

        tmrInner.Enabled = false;

        MessageBox.Show("排序结束!", "消息", MessageBoxButtons.OK, MessageBoxIcon.Information);

        iOuter = 0;//为下一次排序重新设置

    }

}

4、使用Timer控件tmrInner控制排序内层循环的实现,具体实现代码如下:

private void tmrInner_Tick(object sender, EventArgs e)

{

    if (jInner < numbers.Length)

    {   //确定最小值的位置

        if (numbers[jInner] < numbers[k])

        {   //恢复原最小值标签的颜色

            lblNumbers[k].ForeColor = Color.Yellow;

            lblNumbers[k].BackColor = Color.Red;

            k = jInner;

            //重新设置新的最小值标签的颜色

            lblNumbers[k].ForeColor = Color.Red;

            lblNumbers[k].BackColor = Color.Yellow;

        }

        else

        {   //恢复已经搜索过的标签的颜色

            lblNumbers[jInner].ForeColor = Color.Yellow;

            lblNumbers[jInner].BackColor = Color.Red;

        }

        jInner = jInner + 1;

        if (jInner < numbers.Length)

        {

            //设置搜索标签的颜色

            lblNumbers[jInner].ForeColor = Color.Blue;

            lblNumbers[jInner].BackColor = SystemColors.Control;

        }

    }

    else

    {    if (k != iOuter)

        {//当前位置的数据和剩余数据中最小的交换位置

            int temp = numbers[iOuter];

            numbers[iOuter] = numbers[k];

            lblNumbers[iOuter].Text = numbers[iOuter].ToString();

            lblNumbers[iOuter].ForeColor = Color.Black;

            lblNumbers[iOuter].BackColor = SystemColors.Control;

            numbers[k] = temp;

            lblNumbers[k].ForeColor = Color.Yellow;

            lblNumbers[k].BackColor = Color.Red;

            lblNumbers[k].Text = numbers[k].ToString();

        }

        else

        {

            lblNumbers[k].ForeColor = Color.Black;

            lblNumbers[k].BackColor = SystemColors.Control;

        }

        iOuter = iOuter + 1;

string rr = "";

for (int jj = 0; jj <= numbers.Length - 2; jj++)

{

            rr = rr + numbers[jj].ToString() + " ";

}

rr = rr + numbers[numbers.Length - 1].ToString();

        {  //每趟排序的结果显示在文本框中

           txtResult.Text = txtResult.Text + (char)13 + (char)10 + "" + iOuter.ToString() + " 遍排序结果:" + rr;

}

        tmrOuter.Enabled = true;

        tmrInner.Enabled = false;

    }

}

5、“重置”命令按钮,停止当前的排序,清空原有的信息,实现代码如下:

private void btnClear_Click(object sender, EventArgs e)

{   //停止排序

    tmrOuter.Stop();

    tmrInner.Stop();

    this.txtResult.Clear();  //清除文本框的内容

    numbers=new int[1];

    this.panNumber.Controls.Clear();

}

6、“开始排序”命令按钮,启动排序过程,代码如下:

private void btnSort_Click(object sender, EventArgs e)

{

    if (numbers.Length < 10)

    {

        MessageBox.Show("没有生成数据!", "错误提示");

        return;

    }

    //启动定时器,开始排序过程

    tmrOuter.Enabled = true;

}

四、程序运行界面


 


程序运行的界面如下所示,运行时,先确定要排序的数据个数,然后单击“生成数据”命令按钮,可以重新设定排序的数据,单击“开始排序”命令按钮,开始排序过程。在排序过程中,已经排好序的数据序列、当前的最小值、以及动态的搜索过程等环节都能够清楚、直观的看到。

 

五、结语

程序中使用基本的控件设计出效果良好的程序,希望此程序能起到抛砖引玉的作用,大家可以据此将其他的一些典型的计算机算法编程实现直观化,让抽象的东西不再那么难于理解。

 

  推荐精品文章

·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089