七大排序
一、冒泡排序
冒泡排序应该是我们最早接触的排序方式,也是较为简单的一种排序方式.
其思想主要是:
下面是用代码进行实现:
n是指数组大小
以升序排序作为例子
void BullueSort(int* a,int n)
{
第一层循环控制比较个数
for(int i = 0;i<n; i++)
{
第二层循环控制比较次数
j如果从0开始,并且是a[j]与a[j+1]进行比较的话
那么j的上限一定是 n-i-1.
这是为什么呢?
以n=5,i=0为例
那么j<4.那么就存在j=0,1,2,3
j+1 = 1,2,3,4.恰好比较完
因为每一次排序以后,一定能够确定一个值的位置
那么下一次就少比较一个数.这是为什么减i.
至于-1是因为j+1的上限一定是在n-1,
那么j的范围一定是在n-2
for(int j = o;j<n-i-1; j++)
{
if(a[j]>=a[j+1])
{
int tmp =a[j];
a[j]=a[j+1];
a[j+1]=tmp;
}
}
还有另外一种方式:
以j=1开头,用a[j-1]与a[j]进行比较.
for(j=1;j<n-i;j++)
{
if(a[j-1]>=a[j])
{
int tmp =a[j-1];
a[j-1]=a[j];
a[j]=tmp;
}
}
如果要进行降序排序,那么将>=改为<=即可.
}
}
随机产生10个10以下的数,进行排序:
二、选择排序
代码实现:
void Swap(int* a, int* b)
{
int tmp =*a;
*a=*b;
*b=tmp;
}
void SelectSort(int* a,int n)
{
int begin =0;
int end =n-1;
while(begin<=end)
{
int mini =begin;
int maxi= begin;
for(int i =begin;i<end;i++)
{
if(a[i]>a[maxi])
maxi = i;
if(a[i]<a[mini])
mini = i;
}
Swap(&a[mini],&a[begin]);
如果begin = maxi,那么上面交换最小值以后,
此时begin的位置放的是最小值的值,但是此时maxi的位置
也在这里的话就会出错.
因此将mini原来的位置交给maxi就可以了
特殊情况的处理
if(begin == maxi)
{
maxi =mini;
}
Swap(&a[maxi],&a[end]);
begin++;
end--;
}
}
三、插入排序
代码实现:
void InsertSort(int*a,int n)
{
for(int i = 0;i<n;i++)
{
int end = i;
int temp =a[end+1];
while(temp<a[end]&&end>=0)
{
a[end+1]=a[end];
end--;
a[end+1]=temp;
}
}
}
四、希尔排序
代码实现:
void ShellSort(int* a,int n)
{
int gap = n;
当gap=1时,是插入排序,gap>1的过程就是在进行预排序。
while(gap>1)
{
gap = gap/3 +1;
i控制在n-gap,为了保证 end+gap不越界
for(int i = 0;i<n-gap;i++)
{
下标end是为了方便比较
int end = i;
int tmp =a[end];
while(end>=0)
{
if(a[end]>a[end+gap])
{
Swap(&a[end],&a[end+gap]);
end -=gap;
}
else
break;
}
}
}
}
五、堆排序
代码实现:
以建大堆为例
向下调整法
void AdjustDown(int* a,int n,int root)
{
int parent =root;
int child =parent*2+1;
while(child<n)
{
如果建小堆的话,就将< 换为 >
if(a[child]<a[child+1]&&child+1<n)
child++;
if(a[parent]<a[child])
{
Swap(&a[parent],&achild);
parent = child;
child =parent*+1;
}
else
break;
}
}
void HeapSort(int* a,int n)
{
先将数组建堆
for(int i = n;i>=0;i--)
{
AdjustDown(a,n,i-1);
}
while(n>0)
{
再将每个栈顶元素与最后一个元素交换
Swap(&a[0],&a[n-1]);
交换以后,有一个值确定好了位置,
那么总数得减1
n--;
此时不再是一个堆,因此得向下继续建堆
AdjustDown(a,n,0);
}
}
六、快速排序
代码实现:
void QuickSort(int* a,int left,int right)
{
if(right<=left)
{
return;
}
int begin =left;
int end =right;
int key =begin;
while(begin<end)
{
while(begin<end && a[end]>=a[key])
{
end--;
}
while(begin<end && a[begin]<=a[key])
begin++;
Swap(&a[end],&a[begin]);
}
Swap(&a[begin],&a[key]);
key = begin;
QuickSort(a,0,key-1);
QuickSort(a,key+1,right);
}
这只是一种快排的方式,且用的递归。
七、归并排序(递归实现)
代码实现:
void _MergeSort(int* a,int begin,int end,int* tmp)
{
if(begin >= end)
return;
int mid = (begin+end)/2;
_MergeSort(a,begin,mid,tmp);
_MergeSort(a,mid+1,end,tmp);
left1 right1 作为第一组的开头和结尾
left2 right2 作为第二组的开头和结尾
int left1 =begin;
int left2 =mid+1;
int right1 =mid;
int right2 =end;
int i =left1;
利用tmp进行接收
while(left1<=right1 && left2 <=right2)
{
if(a[left1]>a[left2])
tmp[i++] = a[left2++];
else
tmp[i++] = a[left1++];
}
while(left1<=right1)
tmp[i++]=a[left1++];
while(left2<=right2)
tmp[i++]=a[left2++];
再拷贝到数组a中
memcpy(a+begin,tmp+begin,(end-begin+1)*sizeof(int))
}
void MergeSort(int*a,int n)
{
int* tmp =(int*)malloc(sizeof(int)*n);
_MergeSort(a,0,n-1,tmp);
free(tmp);
}