.net 數據結構與算法基礎:高級排序

希爾排序


基本思想


先取一個小於n的整數d1作爲第一個增量,把文件的全部記錄分成(n除以d1)個組。所有距離爲d1的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然後,取第二個增量d2<d1重複上述的分組和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有記錄放在同一組中進行直接插入排序爲止。

計算方法


  屬於插入類排序,是將整個無序列分割成若干小的子序列分別進行插入排序
  排序過程:先取一個正整數d1<n,把所有序號相隔d1的數組元素放一組,組內進行直接插入排序;然後取d2<d1,重複上述分組和排序操作;直至di=1,即所有記錄放進一個組中排序爲止
  初始:d=5
  49 38 65 97 76 13 27 49 55 04
  49 13
  |-------------------|
  38 27
  |-------------------|
  65 49*
  |-------------------|
  97 55
  |-------------------|
  76 04
  |-------------------|
  一趟結果
  13 27 49* 55 04 49 38 65 97 76
  d=3
  13 27 49* 55 04 49 38 65 97 76
  13 55 38 76
  |------------|------------|------------|
  27 04 65
  |------------|------------|
  49* 49 97
  |------------|------------|
  二趟結果
  13 04 49* 38 27 49 55 65 97 76
  d=1
  13 04 49* 38 27 49 55 65 97 76
  |----|----|----|----|----|----|----|----|----|
  三趟結果
  04 13 27 38 49 49 55 65 76 97

程序實現


        public void sort()
        {
            int temp;
            int h = 3;
            while (h > 0)
            {
                int inner;
                for (int outer = h; outer < list.Count; outer++)
                {
                    temp=(int)list[outer];
                    inner=outer;
                    while ((inner - h) > -1 && (int)list[inner - h] >= temp)
                    {
                        list[inner] = list[inner - h];
                        inner -= h;
                    }
                    list[inner] = temp;
                }
                h = (h - 1)%3;
            }
        }


歸併排序



算法思想


設歸併排序的當前區間是R[low..high],分治法的三個步驟是:
①分解:將當前區間一分爲二,即求分裂點
                  

②求解:遞歸地對兩個子區間R[low..mid]和R[mid+1..high]進行歸併排序;
③組合:將已排序的兩個子區間R[low..mid]和R[mid+1..high]歸併爲一個有序的區間R[low..high]。
  遞歸的終結條件:子區間長度爲1(一個記錄自然有序)。

算法過程


算法MergeSortDC的執行過程如下圖所示的遞歸樹。


算法程序

       

       public void sort()
        {
            int[] temp = new int[list.Count];
            RecSort(temp,0,list.Count-1);
        }


        private void RecSort(int[] temp, int lbound, int ubound)
        {
            if (lbound == ubound)
            {
                return;
            }
            else
            {
                int mid = (int)(lbound + ubound) / 2;
                RecSort(temp,lbound,mid);
                RecSort(temp,mid+1,ubound);
                Merge(temp,lbound,(mid+1),ubound);
            }


        }


        private void Merge(int[] temp, int lbound, int highp, int ubound)
        {
            int low = lbound;
            int mid = highp - 1;
            int j=0;
            int n = (ubound - low) + 1;
            while((lbound<=mid)&&(highp<=ubound))
            {
                if ((int)list[lbound] < (int)list[highp])
                {
                    temp[j] = (int)list[lbound];
                    j++;
                    lbound++;
                }
                else
                {
                    temp[j] = (int)list[highp];
                    j++;
                    highp++;
                }
            }
            while (lbound <= mid)
            {
                temp[j] = (int)list[lbound];
                j++;
                lbound++;
            }
            while (highp <= ubound)
            {
                temp[j] = (int)list[highp];
                j++;
                highp++;
            }
            for (int i = 0; i < n; i++)
            {
                list[low + i] = temp[i];
            }
        }


堆排序


算法思想


1)將初始待排序關鍵字序列(R1,R2....Rn)構建成大頂堆,此堆爲初始的無序區;

2)將堆頂元素R[1]與最後一個元素R[n]交換,此時得到新的無序區(R1,R2,......Rn-1)和新的有序區(Rn),且滿足R[1,2...n-1]<=R[n]; 

3)由於交換後新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,......Rn-1)調整爲新堆,然後再次將R[1]與無序區最後一個元素交換,得到新的無序區(R1,R2....Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數爲n-1,則整個排序過程完成。


算法過程


給定一個整形數組a[]={16,7,3,20,17,8},對其進行堆排序。首先根據該數組元素構建一個完全二叉樹:




算法程序


        public void Sort()
        {
            nodes=new Node[list.Count];
            int num=list.Count;
            for (int i = 0; i < list.Count; i++)
            {
                InsertArray(i,(int)list[i]);
            }
            Console.WriteLine();
            for (int i = (int)(num / 2) - 1; i >= 0; i--)
            {
                shifDown(i);
            }
            for (int i = num - 1; i >= 0; i--)
            {
                Node bigNode = Remove();
                Insert(i, bigNode);
            }
            Display();
        }


        private void InsertArray(int i, int p)
        {
            nodes[i] = new Node(p);
            currSize++;
        }


        private void Display()
        {
            Console.WriteLine();
            for (int i = 0; i < nodes.Length; i++)
            {
                Console.Write(nodes[i].data+"  ");
            }
        }


        
        private Node Remove()
        {
            Node fnode=nodes[0];
            currSize--;
            nodes[0] = nodes[currSize];
            shifDown(0);
            return fnode;
        }


        private void shifDown(int index)
        {
            Node node = nodes[index];
            int largeChild;
            while (index < (int)((currSize) / 2))
            {
                int rightChild = index * 2 + 2;
                int leftChild = index * 2 + 1;
                if ((rightChild < currSize) && (nodes[leftChild].data < nodes[rightChild].data))
                {
                    largeChild = rightChild;
                }
                else
                {
                    largeChild = leftChild;
                }
                if (node.data > nodes[largeChild].data)
                {
                    break;
                }
                nodes[index] = nodes[largeChild];
                index = largeChild;
            }
            nodes[index] = node;
        }


        private void Insert(int i, Node p)
        {
            nodes[i] = p;
        }


快速排序


算法思想


1.先從數列中取出一個數作爲基準數。

2.分區過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。

3.再對左右區間重複第二步,直到各區間只有一個數。


算法步驟

87 91 65 72 84 99 89


 分割點值:87         First                                                                                               Last

1)使First自增,直到它大於分割點值爲止,如圖:它停止與91

2)使Last自減,直到它小於或等於分割點值爲止

87 91 65 72 84 99 89


                              First                                                          Last

3)將First值與Last值交換,並使First自增,Last自減


87 84 65 72 95 99 89


                                                    First              Last

4)使First自增,直到它大於分割點值或者大於Last,使Last自減,直到直到它小於或等於於分割點值或者小於First



87 84 65 72 95 99 89


                                                                       First                    
                                                                       Last


87 84 65 72 95 99 89


                                                                       Last              First                    

5)將分割點值與Last值交換


72 84 65 87 95 99 89


                                                                         Last                First    

6)重複以上步驟,直至排序完成。        

可以發現,一輪排序後,大於分割點值(87)的值全部分佈在87右邊,小於87的值全部分佈在左邊     

程序實現            


public QuickSort(ref ArrayList list1)
        {
            list = list1;
        }
        public void sort()
        {
            RecQSort(0,list.Count-1);
        }


        private void RecQSort(int lbound, int ubound)
        {
            if ((ubound-lbound)<=0)
            {
                return;
            }
            else
            {
                int part = partition(lbound, ubound);
                RecQSort(lbound, part - 1);
                RecQSort(part + 1, ubound);
            }
        }


        private int partition(int lbound, int ubound)
        {
            int thefirst = lbound;
            int pivot=(int)list[lbound];
            bool OkSide;
            lbound++;
            do
            {
                OkSide = true;
                while (OkSide)
                {
                    if ((int)list[lbound] > pivot)
                    {
                        OkSide = false;
                    }
                    else
                    {
                        lbound++;
                        OkSide = (lbound <= ubound);
                    }
                }
                OkSide = true;
                while (OkSide)
                {
                    if ((int)list[ubound] <= pivot)
                    {
                        OkSide = false;
                    }
                    else
                    {
                        ubound--;
                        OkSide = (lbound <= ubound);
                    }
                }
                if (lbound < ubound)
                {
                    Swap(lbound, ubound);
                    lbound++;
                    ubound--;
                }
            } while (lbound <= ubound);
            Swap(thefirst,ubound);
            Console.WriteLine("第" + (t++) + "次排序: ");
            Display();
            return ubound;
        }


        private void Swap(int lbound, int ubound)
        {
            int temp=(int)list[lbound];
            list[lbound] = list[ubound];
            list[ubound] = temp;
        }


        private void Display()
        {
            for (int i = 0; i < list.Count; i++)
            {
                Console.Write(list[i] + "  ");
            }
            Console.WriteLine();
        }         


運行結果


  

  

程序地址:http://download.csdn.net/detail/xiang__jiangsu/4809663
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章