DICTATOR第一周排序部分作业

插入、冒泡、选择、归并、快排代码

本文章仅供提交作业及课内交流,并无实际参考学习价值
因尚未弄清楚值传递与引用传递的具体内容,后面二者排序在自由输入数组时会报错,故此处只附上函数体的代码。

插入排序

void Insert(int a[],int n){  //这是插入升序排序的代码
      int i; 
      int j;
      int temp;
      for (i = 1; i < n; i++){  //从第二个数字开始排序
          temp = a[i];  //将“牌”拿在手中
          for (j = i - 1; j >= 0&&a[j] > temp; j--){
              a[j+1] = a[j];
          }
          a[j + 1] = temp;  //插入手里的“牌”
      }
  }

此排序运用扑克牌抓取后排序理解,较为简单。

冒泡排序

void Bubble(int a[],int n){  //这是冒泡生序排序的代码
      int i;
      int j;
      int temp;
      for (i = 1; i < n; i++){
          for(j = n - 1;j >= i;j--){  //每次运行将最小的一个数“冒出”
               if (a[j] > a[j + 1]){  //交换位置
                    temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;  
        }
      }     
    }
  }

顾名思义,冒泡排序的理解方法为进行每次运行时,都可以将一个最小(大)的数按照要求冒出来,我们将它安放在指定位置。运行相应的次数后,得到有序数列。

选择排序

void Selection(int a[],int n){  //这是选择生序排序代码
      int i;
      int j;
      int min;
      int temp;
      for (i = 0; i < n; i++){  //依旧从第二个数字开始排序
          min = i;  //默认最小值下标为开始处下标
          for (j = i; j < n; j++){
              if (a[j] < a[min]){
                  min = j;  //交换下标以选出最小数
              }      
          }
          if(min != i){  //交换位置
            temp = a[i];
            a[i] = a[min];
            a[min] = temp;
          }
      }
  }

一开始做选择排序的时候,没有选取下标而是将该数字直接换位置,写着写着发现和冒泡排序越来越像。后来参考其他博客,明白需要选取下标,最后进行交换。

归并排序

  void Merge(int a[],int left,int mid,int right){  //这是归并生序排序的代码
      int temp[100];
      int begin1 = left;
      int end1 = mid;
      int begin2 = mid + 1;
      int end2 = right;
      int k = 0;

      while (begin1 <= end1 && begin2 <= end2){  //合并两个有序数组
          if (a[begin1] <= a[begin2]){  //将较小的数输入新数组
              temp[k++] = a[begin1++];  //将较小数输入且完成自加
          } else {
              temp[k++] = a[begin2++];
          }
          if(begin2 = end2 + 1){
              while (begin1 <= end1){  //将剩余数字输入
                temp[k++] = a[begin1++];
            }
          }
          if(begin1 = end1 +1){
              while (begin2 <= end2){
                temp[k++] = a[begin2++];
            }
          }
      }
      for (int i = 0, j = left; i < k; i++, j++) {  //将temp内数据转存到a中
		a[j] = temp[i];
	}
  }
  void Mergesort(int a[],int temp[],int left,int right){  //运用递归实现归并排序
      if (right <= left){  //递归跳出条件
          return;
      }
          int mid = (right + left) >> 1;  //将数组二分
          Mergesort(a,temp,left,mid);
          Mergesort(a,temp,mid + 1,right);
          Merge(a,temp,left,mid,right);
          free(temp);
  }

本代码尚未完成调试,切勿照搬

归并排序的算法部分已经完全理解,先从合并两个有序数组开始理解。将对应较小(较大)数置入新的数组储存。

然后更进一步,若是对于两个无序数组,是否就没有办法进行归并排序了呢?

进而联想,若数组内仅有一个元素,必定为有序数组,然后归并排序为二元素数组,再继续向外递推,得到有序数组的排列。

故先用分治思想将数组一次一次二分,得到单一元素后进行归并排序,以递归算法完成程序。

但由于尚未搞定值传递与引用传递的具体内容,本代码未能在主程序成功运行。

快速排序

void Quick(int a[],int left,int right){  //这是快速升序排序的代码
      int i = left;  
      int j = right;  //储存开始数据
      int key = a[left];  //常规定义
      if(left >= right){  //递归跳出条件
          return;
      }
      while (left < right){
          while (key <= a[right]){
              right--;  //向前寻找
          }
          if (key > a[right]){  //将二者交换
              int temp = 0;
              temp = a[left];
              a[left] = a[right];
              a[right] = temp;
              left++;
          }
          while (key >= a[left]){
              left++;  //向后寻找
          }
          if(key < a[left]){
              int temp = 0;
              temp = a[left];
              a[left] = a[right];
              a[right] = temp;
              right--; 
          }
      }
       Quick(a, i, left-1); //用同样的方式对分出来的左边的部分进行同上的做法
       Quick(a, left+1, j); //用同样的方式对分出来的右边的部分进行同上的做法
  }

本代码已经在给定数组的情况下成功运行

我曾经认为快速排序会非常难学,毕竟是应用最多的排序,书中也将其放到了较后的位置。

然而若能很好理解归并排序中的分治思想,快速排序理解没有特别难。

本代码参考另一篇博客的“舞动算法”,下面给出链接:快速排序参考内容

选取一个参考数作为“key”,通过检索整个数组,将比“key”小的数字安放在左边,将比“key”大的数字安放在右边,此后,对于左边和右边新得到的数组,仍然采取相同的办法。以递归算法实现排序,在左右数组仅有一个元素的情况下跳出。最后得到排序好的数列。

近期任务
  • 值传递与引用传递
  • 归并排序与快速排序修正
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值