• 内部排序(上)


    插入类的排序(假设都是从小到大排序的)

    直接插入排序

    思想:每趟将一个待排序的的关键字,按照其关键字值的大小插入到已经排序好的部分序列中。每次都是从后向前比较,为了稳定排序。

    代码如下:

    public void InsertSort(int R[],int n)
     1 public void InsertSort(int R[],int n)
    2 {
    3 for(int i =0;i<n;i++)
    4 {
    5 int temp = R[i]; //保存要插入的值。
    6 int j = i-1;
    7 //找合适的位置,当j<0或者temp>=R[j](表示要插入位置为:j+1)时候结束循环
    8 while(j>=0||temp<R[j])
    9 {
    10 temp[j+1] = temp[j];
    11 }
    12
    13 R[j+1]=temp;
    14 }
    15 }

    折半插入排序

    思想:和直接插入排序基本相同;不同点在于找合适的插入位置用的折半的思想。

    关键点:循环结束的条件。看了好多书上的总感觉瑟瑟的,于是就拿笔算了下。结束条件:用low严格大于high比较好。(这样要插入的地方形式统一即high+1的位置)

    代码如下:

    public static void BinsertSort(int[] R, int n)
     1    public static void BinsertSort(int[] R, int n)
    2 {
    3 for (int i = 0; i < n; i++)
    4 {
    5 int temp = R[i];
    6 int low = 0;
    7 int high = i - 1;
    8 while (low <= high)
    9 {
    10 int mid = (low + high) / 2;
    11 if (temp < R[mid])
    12 {
    13 high = mid - 1;
    14 }
    15 else
    16 {
    17 low = mid + 1;
    18 }
    19 }
    20
    21 //最后要插入的位置为high+1指向的地方。
    22 for (int j = i - 1; j >= high + 1; j--)
    23 {
    24 R[j + 1] = R[j];
    25 }
    26
    27 R[high+1] = temp;
    28 }
    29 }


    希尔排序(缩小增量排序)

    思想:其本质为插入排序,只不过将待排序的的序列按照某种规则分成几个子序列,分别将这几个序列进行直接插入排序。其中规则为增量。

    选择间隔序列可以称得上是一种魔法。只是一个绝对的条件,就是逐渐减小的间隔最后一定要等于1,因此最后一趟排序是一次普通的插入排序。

    eg:

    if(h<5)

      h=1;

    else

    h=(5*h-1)/11;

    也是递减的最后到1。

    ​ 间隔序列中的数字互质通常被认为很重要:这个约束条件使每一趟排序更有可能保持前一趟排序已排好的效果。由增量n分割的一趟排序有n个序列就可以涉及到所有的数。

    代码如下:

    public static void shellsort3(int[] a, int n)
     1 public static void shellsort3(int[] a, int n)
    2 {
    3 int i, j, gap;
    4 for (gap =generateGap(n); gap>0; gap=generateGap(gap))
    5 {
    6 for (i = gap; i < n; i++)
    7 {
    8 //j表示前面的数。
    9 for (j = i - gap; j >= 0 && a[j] > a[j + gap]; j -= gap)
    10 {
    11 int temp = a[j + gap];
    12 a[j + gap] = a[j];
    13 a[j] = temp;
    14 }
    15 }
    16 }
    17 }
    18
    public static int generateGap(int currentGap)
     1     public static int generateGap(int currentGap)
    2 {
    3 if (currentGap == 1)
    4 currentGap = -1;
    5 else if (currentGap < 5)
    6 currentGap = 1;
    7 else
    8 currentGap = (5*currentGap-1)/11;
    9 return currentGap;
    10 }

    交换类排序

    冒泡算法

    思想:通过一系列的“交换”动作完成的。

    (1)第一个元素和第二元素比较,然后在第二个元素和第三元素比较。。。。

    (2)若前面记录的关键码大于后面记录的关键码,则将它们交换,否则不交换。

    (3)不断的重复(1)(2)步骤。

    (4)第一趟排序将最大数放在了最后的位置,第二趟将最大数放在最后第二个位置。。。
    每一趟的排序总是将该段内最大的数浮动到最后(该段内)

    注意:冒泡排序算法结束的调价是一趟排序没有发生元素交换。解决方法:设置一个flag如果flag=0表示结束,或者由结论只要循环n-1次就够了。

    public static void BubbleSort(int[] R, int n)
     1  public static void BubbleSort(int[] R, int n)
    2 {
    3 int temp;
    4 //i控制循环次数n-1次或者可以用个flage来标识这一趟是否有交换元素
    5 //j控制从[0,n-1-i](n代表为数组的长度,因数组是从0开始的所以要n-1,又因为每趟结束都会将最大的数浮动到最后,第i趟最大数则n-1-i即最后第i个位置)
    6
    7 //如果用注释的地方,则选择的标志判断结束,其中i的范围为:[0,n-1]
    8 //即要修改for(int i=0;i<n;i++)
    9 //bool isChange = false;
    10
    11 //由结论只要判断n-1次就够了
    12 for (int i = 0; i < n-1 ; i++)
    13 {
    14 for (int j = 0; j < n - i - 1; j++)
    15 {
    16 if (R[j] > R[j + 1])
    17 {
    18 temp = R[j];
    19 R[j] = R[j + 1];
    20 R[j +1] = temp;
    21 // isChange = true;
    22 }
    23 }
    24
    25 //if (!isChange)
    26 //{
    27 // break;
    28 //}
    29 }
    30
    31 }


    快速排序

    思想:由一个例子引出,军训时,教官说:“第一个同学出列,其他人以他为中心,矮的站他左边,高的站右边”----这就是一趟快速排序。

    关键点:一趟快速排序是以一个“枢轴”,将序列分成两个部分,大的放在“枢轴”右边,小的放在“枢轴”左边。

    ​ ​ ​ ​ 然后在将“枢轴”右边和“枢轴”左边分别进行快速排序

    另一个关键点:快速排序在“切”的时候,采用的交替扫描和交换的过程。(头找大数,尾找小数,找到数就交换

    循环结束条件:i=j,该位置正好是“枢轴”放的位置。

    代码如下:

    public static void QuickSort(ref int[] R, int left, int right)
     1          public static void QuickSort(ref int[] R, int left, int right)
    2 {
    3 int temp;
    4 int i = left;
    5 int j = right;
    6
    7 temp = R[left];//从左边作为“枢轴”
    8 while (left != right)
    9 {
    10 while (right > left && temp < R[right])//尾找小数
    11 right--;
    12
    13 if (left < right)
    14 {
    15 R[left] = R[right];
    16 left++;
    17 }
    18
    19 while (left < right && temp > R[left])//头找大数
    20 left++;
    21
    22 if (left < right)
    23 {
    24 R[right] = R[left];
    25 right--;
    26 }
    27
    28 ​ ​ ​ }
    29 R[left] = temp;//将“枢轴”插入到合适位置即(left=right)的位置
    30
    31 //由第一趟排序之后,以“枢轴”分界点,左边小于“枢轴”右边大于“枢轴”。
    32 //利用递归的思想,如果我将左边再次快速排序,排序完成之后我在把右边的快速排序,那么最终就是一个递增序列。
    33 if (i < left - 1)
    34 {
    35 QuickSort(ref R, i, left - 1);
    36 }
    37
    38 if (j > left + 1)
    39 {
    40 QuickSort(ref R, left + 1, j);
    41 }
    42 }
    43 }

    我们还可以修改更简洁的版本。由于快速排序第一趟找出分界点之后,将分界点的左右再次快速排序。因此我们可以专门写个找分界点的函数Partion(ref int[] R, int left, int right)。然后在左右快速排序即可。
    修改代码如下:

    public static void QuickSortModify(ref int[] R, int left, int right)
     1         public static void QuickSortModify(ref int[] R, int left, int right)
    2 {
    3 int portion;
    4 if (left < right)
    5 {
    6 portion = Partion(ref R, left, right);
    7 QuickSortModify(ref R,left,portion-1);
    8 QuickSortModify(ref R,portion+1,right);
    9 }
    10 }
    public static int Partion(ref int[] R, int left, int right)
     1         public static int Partion(ref int[] R, int left, int right)
    2 {
    3 int temp;
    4 int i = left;
    5 int j = right;
    6
    7 temp = R[left];//从左边作为“枢轴”
    8 while (left != right)
    9 {
    10 while (right > left && temp < R[right])//尾找小数
    11 right--;
    12
    13 if (left < right)
    14 {
    15 R[left] = R[right];
    16 left++;
    17 }
    18
    19 while (left < right && temp > R[left])//头找大数
    20 left++;
    21
    22 if (left < right)
    23 {
    24 R[right] = R[left];
    25 right--;
    26 }
    27 }
    28
    29 R[left] = temp;
    30 return left;
    31 }










  • 相关阅读:
    求算个十百输出
    求算反弹高度
    九九乘法表
    等腰三角形字母
    动态数码管
    静态数码管
    出错的程序操作
    EPLAN
    robotstudio smart组件解释
    eclipse插件安装方法
  • 原文地址:https://www.cnblogs.com/hankskfc/p/2201838.html
Copyright © 2020-2023  润新知