.net 数据结构与算法基础:高级排序

13 篇文章 0 订阅

希尔排序


基本思想


先取一个小于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.再对左右区间重复第二步,直到各区间只有一个数。


算法步骤

87916572849989


 分割点值:87         First                                                                                               Last

1)使First自增,直到它大于分割点值为止,如图:它停止与91

2)使Last自减,直到它小于或等于分割点值为止

87916572849989


                               First                                                          Last

3)将First值与Last值交换,并使First自增,Last自减


87846572959989


                                                     First              Last

4) 使First自增,直到它大于分割点值或者大于Last,使Last自减,直到直到它小于或等于于分割点值或者小于First



87846572959989


                                                                        First                    
                                                                        Last


87846572959989


                                                                        Last              First                    

5)将分割点值与Last值交换


72846587959989


                                                                         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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值