(C/C++学习)9.C/C++优化排序

说明:在C/C++中常见的排序方法有两种,第一种为选择排序法,第二种为冒泡排序法,本文将对这两种排序法进行优化,并给出一种更为快捷的排序法。

 

一.未优化的排序法

现在假如要对一个数组进行排序,假设这个数组为int arr[10],则对该数组元素进行排序常见有两种方法:

 

1.选择排序法

  1 void sortlist1(int *arr,int n)
  2 {
  3     for(int i = 0;i < n-1;i++)
  4     {
  5         for(int j = i+1;j < n;j++)
  6         {
  7             if(arr[i] > arr[j])
  8             {
  9                 arr[i] ^= arr[j];
 10                 arr[j] ^= arr[i];
 11                 arr[i] ^= arr[j];
 12             }
 13         }
 14     }
 15 }

其中arr为待排序的数组名,n为数组中所含的元素个数,内重循环中 arr[i] > arr[j] 决定了排序方式为从小到大;反之则为从大到小。

 

2.冒泡排序法

  1 void sortlist2(int *arr,int n)
  2 {
  3     for(int i = 0;i < n-1;i++)
  4     {
  5         for(int j = 0;j < n-1-i;j++)
  6         {
  7             if(arr[j] > arr[j+1])
  8             {
  9                 arr[j]   ^= arr[j+1];
 10                 arr[j+1] ^= arr[j];
 11                 arr[j]   ^= arr[j+1];
 12             }
 13         }
 14     }
 15 }

其中arr为待排序的数组名,n为数组中所含的元素个数,内重循环中 arr[i] > arr[j] 决定了排序方式为从小到大;反之则为从大到小。

 

二.优化前两种排序方法

 

1.选择排序法的优化(以从小到大的排列顺序为例)

从上面的代码可知,选择排序法的思想是让第 i(i 从0开始) 个元素分别与其后面的每个元素进行比较,当比较结果为大于时,就进行交换,这样比较一轮下来,第i个元素成了此轮比较中的最小元素,再继续比较完所有轮,就实现了数组从小到大的排列。这样的排列使得选择排序法的交换次数过于多,降低了排序效率。所以,对选择排序法的优化方案就是:比而不换,记录下标!

  1 void sortlist(int *p,int n)
  2 {
  3     for(int i = 0;i<n;i++)
  4     {
  5         int idx = i;
  6         for(int j = i+1;j<n;j++)
  7         {
  8             if(p[idx] > p[j])
  9                 idx = j;
 10         }
 11         if(idx != i)
 12         {
 13             p[idx] ^= p[i];
 14             p[i] ^= p[idx];
 15             p[idx] ^= p[i];
 16         }
 17     }
 18 }

如上代码,每次内重循环之后,idx记录本次循环中比较的最小值或最大值(此处为最小值),若idx != i,则说明 i 并不是这次比较的最大或最小值,则进行交换,结束本次循环。

 

2.冒泡排序法优化(以从小到大为例)

冒泡排序法的思想是每轮用第 j(j从0开始) 个元素与第 j+1个元素进行比较,如果大于则交换;这样一轮下来,最大的元素就像冒泡一样到了最后,这样继续比较完所有轮,就实现了冒泡从小到大排序。由此可见,对于冒泡排序法,当某一轮中没有发生过元素的交换时,则表明整个元素序列已经有序了,从而不需要在比较下去。因此,冒泡排序的优化方案为:序而不排。

  1 void sortlist2(int *p,int n)
  2 {
  3     for(int i = 0;i<n;i++)
  4     {
  5         int flag = 0;
  6         for(int j = 0;j<n-1-i;j++)
  7         {
  8 
  9             if(p[j] > p[j+1])
 10             {
 11                 p[j] ^= p[j+1];
 12                 p[j+1] ^= p[j];
 13                 p[j] ^= p[j+1];
 14                 flag = 1;
 15             }
 16         }
 17         if(flag == 0)
 18             break;
 19     }
 20 }

如果在一个内循环之内,都为有序排列,即没发生过交换事件,则标志flag为0,直接退出循环。

 

三.递归排序法

排序思想:对一组元素,选取第一个元素为比较基数,然后其他元素与他进行比较,比它大的放右边,比它小的放左边,一轮完成,该元素左边都是比它自身小的,右边都是比它大的;然后分别对刚才基数左边和右边的元素重复上述操作,直至排序完成。

  1 void sortlist3(int *p,int low,int high)
  2 {
  3     if(low < high)
  4         //判断元素是否大于1,至少2个元素才排序
  5         int l = low;
  6         int h = high;
  7         int middle = p[low ];
  8          //此处只能用p[low],不能用p[0],因为后面递归要用到
  9         while(l < h)
 10         {
 11             while(p[h] >= middle && l<h)
 12                 h--;
 13             p[l] = p[h];
 14             while(p[l] <= middle && l<h)
 15                 l++;
 16             p[h] = p[l];
 17         }
 18         p[h] = middle;
 19         sortlist3(p,low,h-1);
 20         sortlist3(p,h+1,high);
 21     }
 22 }

其中 p 为数组名,low为数组起始地址 0,high 为数组的元素个数减1。

转载于:https://www.cnblogs.com/tuihou/p/9753851.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值