常用的几种排序算法的归纳

插入排序需要注意的几点:

   时间复杂度、空间复杂度尽量要小,稳定性要高(即相同的数字如4521373,经过排序后原来在后面的3还是在那个3的后面)

直接插入排序(接单插入排序):越有序越快、稳定

思想: 直插就是把一个数字插入到一组有序的数组中去,那么对于一组无序的数组,我们怎么样来用这个算法实现呢
一样的,由于第一个数字必定是有序的,我们将第二个数字开始放到临时量tmp中去,然后与这个数字前面的数依次进行比较(此时前面的数字已经是有序的了),放到第一个比他大的数字的位置去就可以了,这样一次对后面的数字进行这种操作最后这个数组就是有序的了,如下图所示:

第一趟:i从下标1开始,与他前面的数4进行比较,由于大于4直接插到4后面就好
第二趟:从下标2开始,此时他前面的数字4、5都是有序的,只要将7放到tmp中去,与他前面的数进行比较,比较到他前一个数即可(由于前面的数必定有序,后面的数就不一定了),然后插入合适位置就好
第三趟:i=3,j=2;与前面两趟的比较过程一样,此时3插到第一个位置,后面的数往后面挪,i在、一直++到最后一个数即可,其过程和前面一样
(1)先从tmp前面查找有没有比他大的有再插入
解法一的世界复杂度较大,O(n^3),最少也有O(n^2)
void S_InsertSort1(int *arr,int len)
{
int tmp;
int i;
int j;
for(int i=1;i<len;i++) 
{
tmp = arr[i];
for(int j=0;j<=i;j++)//遍历tmp前面的值
{
if(arr[j]>tmp) //找到大于tmp的值话,就把后面的值往后移
{
for(int k=i-1;k>=j;k--)
{
arr[k+1] = arr[k];
}
arr[j] = tmp;
break;
}
if(j==i)
{
arr[j] = tmp; //tmp在这组数中最大就还放在这里
}
}

}
}
(2) 改进算法
改进的思想在于将后面两个for循环合并为一个,j从i-1处开始往前遍历,只要>tmp就和他交换
void InsertSort(int *arr,int len)
{
int tmp;
int j;
for(int i=1;i<len;i++)
{
tmp = arr[i];
for(int j=i-1;j>=0;j--)//j从i处开始往前遍历,每当有大于tmp的数时交换数据
{
if(arr[j] > tmp)
{
arr[j+1] = arr[j];
arr[j] = tmp;
}
}
}
}
改进的算法时间复杂度为O(n^2),最好的情况下可以达到O(n)

冒泡排序:时间复杂度o(n^2)、稳定、空间复杂度O(1)

思想:每次把最大的数字放到最后面,j每次从下标0开始往后走,由于每次都把最大的数字放到最后一个,所以j只用走到待排序数的前一个就好。如下图所示,7,8是已经排好了的,这个时候j只用走到下标3即可,因为7,8已经是排好的两个最大的了,没必要再往后走

void BubbleSort(int *arr,int len)
{
int tmp;
for(int i=1;i<len;i++)
{
for(int j=0;j<len-i;j++)
{
if(arr[j] > arr[j+1])
{
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}

选择排序:时间复杂度O(n^2)、不稳定(待排序序列中最小的数和第一个数交换时可能把这个数交换到与他相等本来在他后面的数的后面)

思想:每次选择最小的数和带排序序列中的第一个数交换
注意:由于每次都要遍历序列找到那个最小的数然后和待排序序列的第一个数交换,一定要保存那个最小的数的下标再次才能找到
void SelectSort(int *arr,int len)
{
int minIndex;//用来保存最小的数的下标
int tmp;
for(int i=0;i<len-1;i++)
{
for(int j=i;j<len;j++)//j从i下标处往后遍历
{
minIndex = i;
if(arr[minIndex] > arr[j])
{
minIndex = j;
}
}
tmp = arr[i];//待排序序列的第一个数保存其中最小的数
arr[i] = arr[minIndex];
arr[minIndex] = tmp;
}
}

快速排序:时间复杂度O(n*logn),空间复杂度O(logn),不稳定

思想:定义一个low、定义一个high将low指向的数据作为基准,从high指向的位置往前查找,有比他小的插入到low处,从low处往后查找,有比他大的放到high处
int Partition(int *arr,int low,int high)//一次排序
{
int tmp = arr[low];
while(low < high)
{
while((low<high) && (arr[high]) >= tmp)
{
high--;
}
if(low == high)
{
break;
}
else
{
arr[low] = arr[high];
}
while((low<high) && (arr[low]) <= tmp)
{
low++;
}
if(low == high)
{
break;
}
else
{
arr[high] = arr[low];
}
}
arr[low] = tmp;
return low;
}
void Quick(int *arr,int low,int high)//一个待排序列用递归的方法使用快速排序
{
int par = Partition(arr,low,high);
if(par-1 > low)
{
Quick(arr,low,par-1);
}
if(par+1 < high)
{
Quick(arr,par+1,high);
}
}
void QuickSort(int *arr,int len)//马甲函数,实现面向对象,方便用户调用这个函数直接可以使用
{
Quick(arr,0,len-1);
}

归并排序:时间复杂度O(n*logn),空间复杂度O(1),不稳定

思想:建成大根堆,从下往上建堆,从上往下调整.每次讲待排序序列的最后一个数字和0下标值进行交换
在这里用到两个公式
1、由父节点n推左右孩子节点为2*n+1、2*n+2
2、由孩子节点n推父节点(n-1)/2
void HeapAdjust(int *arr,int start,int end)//一次建堆
{
int tmp = arr[start];
for(int i=2*start+1;i<=end;i=2*i+1)//每次都开始遍历左孩子,右孩子可能没有
{
if((i+1<=end) && (arr[i])<arr[i+1])
{
i++;//i保存左右节点中较大的值的下标
}
if(arr[i] > tmp)
{
arr[start] = arr[i];
start = i;
}
else
{
break;
}
}
arr[atsrt] = tmp;
}
void HeapSort(int *arr,int len)
{
int tmp;
int i;
for(int i=(len-1-1)/2;i>=0;i--)//建堆
{
HeapSort(arr,i,len-1);
}
for(i=0;i<len-1;i++)
{
tmp = arr[0];
arr[0] = arr[len-1-i];
arr[len-1-i] = tmp;
HeapAdjust(arr,0,len-1-i-1);
}
}

归并排序

思想:每两个数一组,两个中小的放到前面,两两有序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值