首页 > 代码库 > 算法案例

算法案例

1、冒泡(Bubble)

        7 5 2 1 5 9
        5 7 2 1 5 9
        5 2 7 1 5 9
        5 2 1 7 5 9
        5 2 1 5 7 9

        2 5 1 5 7 9
        2 1 5 5 7 9
        2 1 5 5 7 9

        1 2 5 5 7 9


    public static void BubbleSort(int[] a)
        {
            int n = a.Length - 1;//个数
            int i, j;//用于控制循环
            int tmp;//中间变量
            bool isChange;//记录冒泡一轮下来是否发生交换(如果没有发生交换证明已排好序)
            for (i = 0; i < n; i++)
            {
                isChange = false;
                for (j = 0; j < n - i; j++)//每轮冒泡过后要对比的数就少一个
                {
                    if (a[j] > a[j + 1])//大的数向上冒
                    {
                        tmp = a[j];
                        a[j] = a[j + 1];
                        a[j + 1] = tmp;
                        isChange = true;
                    }
                }
                if (!isChange)
                {
                    return;
                }
            }
            return;
        }

2、直接插入(Insert)

        7 5 2 1 5 9
        5 7 2 1 5 9
        2 5 7 1 5 9
        1 2 5 7 5 9
        1 2 5 5 7 9

       public static void InsertSort(int[] a)
        {
            int n = a.Length;
            for (int i = 1; i < n; i++)//循环从第二个数组元素开始,因为arr[0]作为最初已排序部分
            {
                int temp = a[i];//temp标记为未排序第一个元素
                int j = i - 1;
                while (j >= 0 && a[j] > temp)//将temp与已排序元素从小到大比较,寻找temp应插入的位置
                {
                    a[j + 1] = a[j];
                    j--;
                }
                a[j + 1] = temp;
            }
        }


3、直接选择(Select)

        7 5 2 1 5 9
        1 5 2 7 5 9
        1 2 5 7 5 9
        1 2 5 7 5 9
        1 2 5 5 7 9


   

     public static void SelectSort(int[] a)
        {
            int n = a.Length;//个数
            int i, j;
            int tmp;
            int b;
            for (i = 0; i < n - 1; i++)
            {
                tmp = i;
                for (j = i + 1; j < n; j++)
                {
                    if (a[tmp] > a[j])//每轮找到最小的元素
                        tmp = j;
                }
                if (i != tmp)
                {
                    b = a[tmp];
                    a[tmp] = a[i];
                    a[i] = b;
                }
            }
        }


4、快速(Quick)

        7       5 2 1 5 9
        5   2 1 5     7 9
        2 1 5   5     7 9
        1 2 5   5     7 9




      

  public static void QuickSort(int[] a, int low, int high)
        {
            if (low < high)
            {                                     // ↓                     ↓
                int point = MovePart(a, low, high);// 5 6 2 1 4 9      4 1 2 5 6 9
                QuickSort(a, low, point);
                QuickSort(a, point + 1, high);
            }
        }
        public static int MovePart(int[] a, int partLow, int partHigh)
        {
            int pivotP = partLow;//记住枢纽位置
            while (partLow < partHigh)
            {
                while (partLow < partHigh && a[partHigh] >= a[pivotP])//右往左找第一个小于pivot的数
                {
                    partHigh--;
                }
                Swap(a, pivotP, partHigh);
                pivotP = partHigh;
                while (partLow < partHigh && a[partLow] <= a[pivotP])//左往右找第一个大于prvot的数
                {
                    partLow++;
                }
                Swap(a, partLow, pivotP);
                pivotP = partLow;
            }
            return pivotP;//返回分割点
        }
        public static void Swap(int[] a, int pivotP, int swapP)
        {
            int t;
            t = a[pivotP];
            a[pivotP] = a[swapP];
            a[swapP] = t;
        }


5、希尔(Shell)

        7 5 2 1 5 9
        7 5 2   1 5 9
        7 5   2   1 5  9
        5 7   2   1 5  9
        2 5   7   1 5  9
        2 5 7   1 5 9
        1 2 5 7 5 9
        1 2 5 5 7 9


     

   public static void ShellSort(int[] a)
        {
            int n = a.Length;
            for (int incr = 3; incr > 0; incr--)//增量递减,增量据说以9 5 3 1最优(各种大牛到现在都没有定论),此处为3 2 1
            {
                for (int L = 0; L < (n - 1) / incr; L++)//重复分成的每个子列表
                {
                    for (int i = L + incr; i < n; i += incr)//对每个子列表应用插入排序
                    {
                        int temp = a[i];
                        int j = i - incr;
                        while (j >= 0 && a[j] > temp)
                        {
                            a[j + incr] = a[j];
                            j -= incr;
                        }
                        a[j + incr] = temp;
                    }
                }
            }
        }


6、归并(Merge)

        7 5 2 1 5 9
        7 5 2    1 5 9
        7   5 2   1   5 9
        7   2 5   1   5 9
        2 5 7    1 5 9
        1 2 5 5 7 9


    

    public static void Merge(int[] a, int low, int center, int high)
        {
            if (low >= high) return;
            int m = center - low + 1;
            int n = high - center;
            int[] L = new int[m];
            int[] R = new int[n];
            int i, j, k;
            for (i = 0; i < m; ++i) L[i] = a[low + i];//取得左边数
            for (i = 0; i < n; ++i) R[i] = a[low + i + m];//取得右边数
            for (i = 0, j = 0, k = low; i < m && j < n; ++k)
            {
                if (L[i] > R[j])//从L、R两边选比较小的数放进a,直到一边放完
                {
                    a[k] = R[j];
                    j++;
                }
                else
                {
                    a[k] = L[i];
                    i++;
                }
            }
            while (i < m)//如果是L没放完,把L剩余的数放进a
            {
                a[k] = L[i];
                k++;
                i++;
            }
            while (j < n)//如果是R没放完,把R剩余的数放进a
            {
                a[k] = R[j];
                k++;
                j++;
            }
        }
        public static void MergeSort(int[] a, int low, int high)
        {
            int center;
            if (low < high)
            {
                center = (low + high) / 2;
                MergeSort(a, low, center);
                MergeSort(a, center + 1, high);
                Merge(a, low, center, high);
            }
        }


7、堆(Heap)

        7 5 2 1 5 9
            7
           / \
          5   2
         / \ / \
         1 5 9

            9
           / \
          5   7
         / \ / \
         1 5 2

        /// <summary>
        /// 堆排序,此处为倒序,要升序,请使用大二叉堆,或对数组进行首尾交换
        /// </summary>
        /// <param name="a"></param>
        /// <param name="n"></param>
        public static void HeapSort(int[] a, int n)
        {
            MakeMinHeap(a, n);//将数组建立成最小堆
            for (int i = n - 1; i >= 1; i--)
            {
                Swap(a, i, 0);//把该论得到的最小数排到末尾已拍好序的的数前
                MinHeapFixDown(a, 0, i);//排除末尾拍好序的的数得出子二叉堆,在作调整得出新的二叉堆,root又为最小的数
            }
        }
        /// <summary>
        /// 新加入叶子结点 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="leafPoint">叶子结点所在位置</param>
        public static void MinHeapAddPoint(int[] a, int leafPoint)//以叶子结点,叶子结点的父结点,叶子结点的爷结点...为一组进行直接插入
        {
            int fartherPoint, temp,currentPornt;
            temp = a[leafPoint];
            currentPornt = leafPoint;//记录当前节点位置
            fartherPoint = (leafPoint - 1) / 2;      //父结点  
            while (a[fartherPoint] > a[currentPornt]&& currentPornt!=0)
            {
                a[currentPornt] = a[fartherPoint];
                currentPornt = fartherPoint;
                fartherPoint = (currentPornt - 1) / 2;//父结点为的位置为 (currentPoint - 1) / 2
            }
            a[currentPornt] = temp;
        }
        /// <summary>
        /// 在最小堆中加入新的数据num  (从叶子结点(数组尾)插入)
        /// </summary>
        /// <param name="a"></param>
        /// <param name="n">新增结点位置(数组结尾位置+1 即 数组长度)</param>
        /// <param name="num">新增结点值</param>
        public static void MinHeapAddNumber(int[] a, int n, int num)
        {
            a[n] = num;
            MinHeapAddPoint(a, n);
        }
        /// <summary>
        /// 删除跟结点(将最后的结点a[n]放到根节点a[0]的位置)后的堆调整
        /// 从i整节点向下开始调整,n为节点总数, 从0开始计算 i节点的子节点为 2*i+1, 2*i+2  
        /// </summary>
        /// <param name="a">数组</param>
        /// <param name="fatherPoint">要调整的位置</param>
        /// <param name="n">二叉堆的长度(要调整到数组的那个位置)</param>
        public static void MinHeapFixDown(int[] a, int fatherPoint, int n)
        {
            int sonPoint, temp;
            temp = a[fatherPoint];
            sonPoint = 2 * fatherPoint + 1;//左子结点,右子节点为sonPoint+1 子节点为 2*i+1, 2*i+2
            while (sonPoint <n)
            {
                if (sonPoint + 1 < n && a[sonPoint + 1] < a[sonPoint]) //存在右子结点的话,在左右孩子中找较小数  
                    sonPoint++;
                if (a[sonPoint] >= temp)//再和父结点对比,如果父结点比较大不用做交换
                    break;
                else
                {//否则把较小的子结点往上移动,替换它的父结点  
                    a[fatherPoint] = a[sonPoint];     
                    fatherPoint = sonPoint;
                    sonPoint = 2 * fatherPoint + 1;
                }
            }
            a[fatherPoint] = temp;
        }
        /// <summary>
        /// 在最小堆中删除数(删除根节点)
        /// </summary>
        /// <param name="a"></param>
        /// <param name="n">结点个数</param>
        public static void MinHeapDeleteNumber(int[] a, int n)
        {
            Swap(a, 0, n - 1); //互换根节点和叶子结点后
            MinHeapFixDown(a, 0, n - 1);//向下调整
        }
   
        /// <summary>
        /// 建立最小堆 n为结点总数
        /// </summary>
        /// <param name="a">数组</param>
        /// <param name="n">结点总数</param>
        public static void MakeMinHeap(int[] a, int n)
        {
            for (int i = (n-1-1)/ 2 ; i >= 0; i--)//由最后一个结点的父结点开始向下调整
                MinHeapFixDown(a, i, n);
        }

算法案例