您的位置:首页 > 理论基础 > 数据结构算法

数据结构排序--冒泡与选择

2017-09-03 13:39 281 查看

前文:

     在数据结构中,排序是必不可少,也是必须要熟练的掌握几种,因为这些排序方法可以帮助我们在处理非常庞大以及无规律的数据时大大的减少时间的浪费,并且提高我们代码的性能。下面我将会讲解排序的原理及代码实现和它们的时间复杂度与空间复杂度,稳定性。

时间复杂度:执行算法所需要的计算工作量。
空间复杂度:执行算法所需要的内存空间。
稳定性:指排序前相同数的相对位置,在排序后也未发生改变。

正文: 

一:最简单的排序------冒泡排序(未优化)
冒泡排序的原理是两两进行比较。例如当我们要排序一组数组是int arr[]={33,45,18,92,11,75,68}。



我们可以先把前面2个拿出来进行比较,我们把大的数放后面,那么第一趟比较,就是,先是33和45比较。45比较大,位置不变,然后45和18比较,45大,所以二者交换位置得:



然后45和92比较,92大,位置不变,92和11比较,92大,交换位置:



同理之后。
第一趟结束之后就会得到33,18,45,11,75,68,95。
那么第二趟比较的时候,继续从前面的2个进行比较,只是这次比较将不会比较到末尾,因为95已经是第一趟排好最大的数值。以此类推,一共排序sizeof(arr)-1趟就能完成排序。

思路完毕之后,我们肯定要用到Swap交换函数,当我们一般写Swap函数时,都用的是创建临时空间,而今天我们可以用不创建临时空间的方法来写Swap函数:
void Swap(int *a, int *b)
{
*a = *a + *b;              //a现在就是a+b
*b = *a - *b;              //b=a+b-b=a  完成交换
*a = *a - *b;              //a=a+b-a+b-b=b   完成交换
}
或者是
void Swap(int *a, int *b)
{
*a = *a^*b;
*b = *b^*a;
*a = *a^*b;
}


那么我们写排序可以直接使用
代码演示:
void Sort(int *arr, int len)                         //时间复杂度  O(n^2)   空间复杂度O(1)    稳定排序
{
int i;
int j;
for (i = 0; i < len-1; i++)                //最后一趟不需要在排,因此是len-1
{
for (j = 0; j < len-i-1; j++)        //从第一个开始,一直到已排好数字前
{
if (arr[j] > arr[j + 1])
{
Swap(arr+j,arr+j+1);
}
}
}
}
现在来想一下,这个代码的效率其实不是很高,因为它必须要排len-1次,如果在len-1次之前早已经排好,甚至本来就是一个有序的序列,那么这样的代码就显得很低效。所以我们来做冒泡的优化:
void Sort(int *arr, int len)             //冒泡排序  时间复杂度O(n^2)   空间复杂度O(1)    稳定排序
{
int i;
int j;
bool mark = true;                      //优化冒泡排序,用一个mark来标记如果已经排好了就不需要继续排下去
for (i = 0; i < len-1; i++)            //只需要比较len-1躺,最后一个数不需要比较
{
mark = true;                       //初始mark是true
for (j = 0; j < len-i-1; j++)
{
if (arr[j] > arr[j + 1])
{
Swap(arr+j,arr+j+1);
mark = false;                   //如果发生了排序,说明还没排好,将mark置为false
}
}
if (mark)                   //如果没有发生排序,说明已经排序好了,则跳出循环,终止排序;
{
break;
}
}
printf("排序了%d次\n", i);
}
这样我们就能够减小冒泡的排序的次数。
二:简单选择排序

我们还是用冒泡排序的例子来讲int arr[]={33,45,18,92,11,75,68}。

直接选择排序就是用一个m来存放每趟默认最小数值下标。让j代表后面数下标,从i开始比较,那么j=i+1,一直往后遍历,找到比m下标的值小的数,就把j下标放入到m下标中,当遍历完整个数组,然后去交换m下标和i下标的数。

第一趟:m下标是0,i也是0,j从i+1开始,找到18比33小,就把18的下标2,放入m中,然后继续往后走,找到11比18小,就把11的下标4放入m中,一直遍历完,m中是4号下标,把4号下标和0下标互换数值。所以就得到 
11,45,18,92,33,75,68   这样我们就把最小值放到了最前面,这样我们就可以从1号下标继续开始排序,依次下去最终完成排序。
实现代码如下:
void Sort(int *arr, int len)           //选择排序   时间复杂度O(n^2)   空间复杂度O(1)   不稳定排序
{
int m;
for (int i = 0; i < len - 1; i++)
{
m = i;                             //默认第一个数值为最小,把它的下标放到m中
for (int j = i + 1; j < len; j++)  //把后面的每一个数都和m下标的数进行比较
{
if (arr[m] > arr[j])            //如果有数比m下标中的数还小,就把这个数的下标放到m中
{
m = j;
}
}
if (m != i)                    //同一个位置不需要排序
{
Swap(arr + m, arr + i);
}
}
}


以上就是数据结构八大排序中最简单的2种,后续将更新,剩余的六种排序原理及优化及代码实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐