C# 多线程排序Demo
时间:2011-05-30 来源:炭炭
  using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Text;
  using System.Windows.Forms;
  namespace AlgorithmSort
  {
   public partial class Form1 : Form
      {
          int[] Array1, Array2, Array3;
          CSort QuicklySort ;
          CSort ShellSort;
          CSort BubbleSort;
          System.Threading.Thread theQuicklySortThread;
          System.Threading.Thread theShellSortThread;
          System.Threading.Thread theBubbleSortThread;
          System.Threading.Thread theDeamonThread;
  
          public Form1()
          {
              InitializeComponent();
              Array1 = new int[100];
              Array2 = new int[100];
              Array3 = new int[100];
              InitializeData(ref Array1);
              Array.Copy(Array1,Array2,Array2.Length);
              Array.Copy(Array1,Array3,Array3.Length);
              QuicklySort = new CSort(panel3);
              ShellSort = new CSort(panel2);
              BubbleSort = new CSort(panel1);
             
          }
          /// <summary>
          /// 用随机数初始化数组A的每一成员
          /// </summary>
          /// <param name="A">通过引用的方式,返回数组A中的数据</param>
          private void InitializeData(ref int[] A)
          {
              System.Random Randomer = new System.Random();
              for (int i = 0; i < A.Length;i++ )
              {
                  A[i] = Randomer.Next() % A.Length;
              }
          }
          /// <summary>
          /// 根据指定数组每一组数据的大小,在Panel上画红线,数据越大,线越长
          /// 注,初始化数组时,使用数组的长度做为数据取值的最大值
          /// </summary>
          /// <param name="thePanel">画线的区域控件</param>
          /// <param name="Array">数据数组</param>
          private void ShowData(System.Windows.Forms.Panel thePanel, int[] theArray)
          {
              System.Drawing.Graphics theGraph = thePanel.CreateGraphics();
              System.Drawing.Pen thePen = new System.Drawing.Pen(System.Drawing.Color.Red);
              System.Drawing.Pen theEraser = new System.Drawing.Pen(thePanel.BackColor);
              for (int i = 0; i < theArray.Length; i++)
              {
                  theGraph.DrawLine(thePen, 0,
                      i * thePanel.ClientRectangle.Height / theArray.Length,
                      theArray[i] * thePanel.ClientRectangle.Width / theArray.Length,
                      i * thePanel.ClientRectangle.Height / theArray.Length
                      );
                  theGraph.DrawLine(theEraser,
                      theArray[i] * thePanel.ClientRectangle.Width / theArray.Length,
                      i * thePanel.ClientRectangle.Height / theArray.Length,
                      thePanel.ClientRectangle.Width,
                      i * thePanel.ClientRectangle.Height / theArray.Length
                      );
              }
          }
          public void BubbleSortProc(Object SortObj)
          {
              if (SortObj is CSort)
              {
                  CSort ASortObj = SortObj as CSort;
                  ASortObj.BubbleSort(ref Array1);
              }
          }
          public void  QuicklySortProc( Object SortObj )
          {
              if (SortObj is CSort)
              {
                  CSort ASortObj = SortObj as CSort;
                  ASortObj.QuickSort(ref Array3, 0, Array3.Length, Array3.Length);
              }
          }
          public void ShellSortProc(Object SortObj)
          {
              if (SortObj is CSort)
              {
                  CSort ASortObj = SortObj as CSort;
                  ASortObj.ShellSort(ref Array2);
              }
          }
         /// <summary>
         /// 三个排序线程的守护线程
         /// </summary>
          public void DeamonProc()
          {
              //等待快速排序线程结束
              while ((theQuicklySortThread != null)
                  && (theQuicklySortThread.ThreadState == System.Threading.ThreadState.Running)
                  )
              {
                  System.Threading.Thread.Sleep(1);
              }
              //等待希尔排序线程结束
              while ((theShellSortThread != null)
                  && (theShellSortThread.ThreadState == System.Threading.ThreadState.Running)
                  )
              {
                  System.Threading.Thread.Sleep(1);
              }
              //等待冒泡排序线程结束
              while ((theBubbleSortThread != null)
                  && (theBubbleSortThread.ThreadState == System.Threading.ThreadState.Running)
                  )
              {
                  System.Threading.Thread.Sleep(1);
              }
              //所有线程排序结束
              //允许下次重新开始
              System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
              this.btnQuit.Enabled = true;
              this.btnRefresh.Enabled = true;
              this.btnStart.Enabled = true;
}
  
          /// <summary>
          /// “数据刷新”按钮的处理函数,重新初始化三个数据数组,并刷新界面显示
          /// </summary>
          /// <param name="sender"></param>
          /// <param name="e"></param>
          private void btnRefresh_Click(object sender, EventArgs e)
          {           
              if(   (theQuicklySortThread.ThreadState== System.Threading.ThreadState.Running)
                  ||(theShellSortThread.ThreadState  == System.Threading.ThreadState.Running)
                  ||(theBubbleSortThread.ThreadState == System.Threading.ThreadState.Running)
                  )
              {
                  return ;
              }
              InitializeData(ref Array1);
              Array.Copy(Array1, Array2, Array2.Length);
              Array.Copy(Array1, Array3, Array3.Length);
              ShowData(panel1, Array1);
              ShowData(panel2, Array2);
              ShowData(panel3, Array3);
              btnStart.Enabled = true;
              btnRefresh.Enabled = false;
}
          /// <summary>
          /// 启动 排序进程按钮 的处理函数
          /// </summary>
          /// <param name="sender"></param>
          /// <param name="e"></param>
          private void BtnStart_Click(object sender, EventArgs e)
          {
              theQuicklySortThread = new System.Threading.Thread(this.QuicklySortProc);
              theShellSortThread = new System.Threading.Thread(this.ShellSortProc);
              theBubbleSortThread = new System.Threading.Thread(this.BubbleSortProc);
              theDeamonThread = new System.Threading.Thread(this.DeamonProc);
              theBubbleSortThread.Start(BubbleSort);
              theShellSortThread.Start(ShellSort);
              theQuicklySortThread.Start(QuicklySort);
              //启动看护线程
              theDeamonThread.Start();
              btnStart.Enabled = false;
              btnRefresh.Enabled = false;
              btnQuit.Enabled = false;
}
          //窗体重画事件处理函数
          private void Form1_Paint(object sender, PaintEventArgs e)
          {
              ShowData(panel1, Array1);
              ShowData(panel2, Array2);
              ShowData(panel3, Array3);
          }
          /// <summary>
          /// 窗体关闭前事件处理函数,如果排序线程没有完成,则不让关闭
          /// </summary>
          /// <param name="sender"></param>
          /// <param name="e"></param>
          private void Form1_FormClosing(object sender, FormClosingEventArgs e)
          {
              if (theBubbleSortThread == null)
                  return;
              if ((theBubbleSortThread.ThreadState == System.Threading.ThreadState.Running)
                  || (theShellSortThread.ThreadState == System.Threading.ThreadState.Running)
                  || (theQuicklySortThread.ThreadState == System.Threading.ThreadState.Running)
                  )
              {
                  e.Cancel = true; //不允许退出;
                 
              }
                
          }
          private void btnQuit_Click(object sender, EventArgs e)
          {
              this.Close();
          }
      }  
   
   public class CSort
   {
          private Panel m_Panel;
          public CSort(Panel newPanel)
          {
              m_Panel = newPanel;
          }
          //根据数据画线
          public void DrawData(int nPos, int nValue,int nMax)
          {
              System.Drawing.Pen thePen = new System.Drawing.Pen(System.Drawing.Color.Red);
              System.Drawing.Pen theEraser = new System.Drawing.Pen(m_Panel.BackColor);
System.Drawing.Graphics theGraph = m_Panel.CreateGraphics();
              theGraph.DrawLine(thePen, 0,
                      nPos * m_Panel.ClientRectangle.Height / nMax,
                      nValue * m_Panel.ClientRectangle.Width / nMax,
                      nPos * m_Panel.ClientRectangle.Height / nMax
                      );
              theGraph.DrawLine(theEraser, nValue * m_Panel.ClientRectangle.Width / nMax,
                      nPos * m_Panel.ClientRectangle.Height / nMax,
                      m_Panel.ClientRectangle.Width,
                      nPos * m_Panel.ClientRectangle.Height / nMax
                      );         
          }
         
          /// <summary>
          /// 交换两个对象引用指向的内容
          /// </summary>
          /// <param name="A"> 交换引用1 </param>
          /// <param name="B"> 交换引用2 </param>
          ///
          public static void Exchange(ref int A, ref int B)
          {
              int tmp = A;
              A = B;
              B = tmp;
          }
         
          /// <summary>
          /// 委托函数 Compare( object A,object B);
          ///比较对象 A,B 关键字大小,如果 A < B则返回 true,否则false
          /// <param name="A">比较大小的参数1</param>
          /// <param name="B">比较大小的参数2</param>
          /// </summary>
          //public delegate bool PCompare(int A, int B);
  
    /// <summary>
          /// 冒泡排序法,把对像数组A中的对象,按一定顺序排列,排列的次序取决于Compare函数的比较方案
    /// </summary>
    /// <param name="A"> 被排序的对象数组</param>
    /// <param name="Compare"> 比较对象关键字大小的函数委托变量</param>
    ///
          //此委托测试用,没实际价值
          //public delegate void Sort(ref T[] A, PCompare Compare);
    public void BubbleSort( ref int[] A)
    {
     bool bFinished = false;
     while (!bFinished)
     {
      bFinished = true;
      for(int i=0; i<A.Length-1; i++)
      {
       if(A[i] > A[i+1])
       {
        //交换
                          Exchange(ref A[i], ref A[i + 1]);
                          DrawData(i, A[i], A.Length);
                          DrawData(i + 1, A[i+1], A.Length);
                          //在m_Panel上同时画线
        //T tmp = A[i];
        //A[i] = A[i+1];
        //A[i+1] = tmp;
        bFinished = false;
       }
      }
     }
    }
    /// <summary>
          /// 希尔(或叫步长)排序法,把对像数组A中的对象,按一定顺序排列,排列的次序取决于Compare函数的比较方案
    /// </summary>
    /// <param name="A"> 被排序的对象数组</param>
    /// <param name="Compare"> 比较对象关键字大小的函数委托变量</param>
    ///
    public void ShellSort( ref int[] A)
    {
              int Step = A.Length / 2;
              bool bSorted = false;
              while ((Step > 1) || (bSorted==false))
              {
                  bSorted = true;
                  for (int i = 0; i < A.Length - Step; i++)
                  {
                      if( A[i] > A[i+Step] )
                      {
                          Exchange(ref A[i],ref A[i + Step]);
                          DrawData(i, A[i], A.Length);
                          DrawData(i + Step, A[i + Step], A.Length);
                          bSorted = false;
                      }
                  }
                  if ((Step > 1) && (bSorted==true))
                  {
                      Step = Step / 2;
                      bSorted = false;
                  }
              }
}
  
    /// <summary>
          /// 快速排序法,把对像数组A中的对象,按一定顺序排列,排列的次序取决于Compare函数的比较方案
    /// </summary>
          /// <param name="A"> 被排序的对象数组</param>
          /// <param name="Compare">比较对象关键字大小的函数委托变量</param></param>
    public void QuickSort( ref int[] A, int nPosStart,int nPosFinish, int nMax)
    {
     if( A.Length <=1 )
              {
                  return ;
              }
              else
     {
      int[] A1,A2;
      //把数组A分成两个子集 A1,A2
                  A1 = new int[(A.Length / 2)];
                  A2 = new int[(A.Length - A.Length/2)];
      for(int i=0;i<A.Length/2;i++)
       A1[i] = A[i];
      for(int i=A.Length/2; i<A.Length;i++)
       A2[i-A.Length/2] = A[i];
      //两个子集数组分别排序
      QuickSort(ref A1,nPosStart,nPosStart+ (int)System.Math.Round((nPosFinish-nPosStart)/2.0f) , nMax);
                  QuickSort(ref A2, (int)System.Math.Round((nPosFinish - nPosStart) / 2.0f) + 1, nPosFinish , nMax);
      //合并两个子集
      int index1=0;
      int index2=0;
      int index =0;
      while ( (index1 <A1.Length) && (index2 <A2.Length))
      {
       if ( A1[index1] > A2[index2])
       {
        A[index++] = A2[index2++];
       }
       else
       {
        A[index++] = A1[index1++];
       }
      }
     
      if (index1 <A1.Length)
      {
       while(index<A.Length)
       {
        A[index++] = A1[index1++];
       }
      }
      else
      {
       while(index<A.Length)
       {
        A[index++] = A2[index2++];
       }
      }
                  //显示数据
                  System.Drawing.Graphics theGraph = m_Panel.CreateGraphics();
                  System.Drawing.Pen thePen = new System.Drawing.Pen(System.Drawing.Color.Red);
                  System.Drawing.Pen theEraser = new System.Drawing.Pen(m_Panel.BackColor);
                  for (int i = 0; i < A.Length; i++)
                  {
                      theGraph.DrawLine(thePen, 0,
                          (i + nPosStart) * m_Panel.ClientRectangle.Height / nMax,
                          A[i] * m_Panel.ClientRectangle.Width / nMax,
                          (i + nPosStart) * m_Panel.ClientRectangle.Height / nMax
                          );
                      theGraph.DrawLine(theEraser,
                          A[i] * m_Panel.ClientRectangle.Width / nMax,
                          (i + nPosStart) * m_Panel.Height / nMax,
                          m_Panel.ClientRectangle.Width,
                          (i + nPosStart) * m_Panel.ClientRectangle.Height / nMax
                          );
                  }
  
     }
    }
}
   
  }










