常用排序算法
常用到的排序算法,大概就就4、5种:冒泡排序,选择排序、快速排序、桶排序、计数排序
我们本篇假设排序是从小到大排序,假设有一个int 数组,1000个元素:
int data[1000];
排序的结果就是:
d a t a [ 0 ] ≤ d a t a [ 1 ] ≤ . . . ≤ d a t a [ 999 ] data[0] ≤ data[1]≤ ...≤data[999] data[0]≤data[1]≤...≤data[999]
思想分类
从排序思想上,我们可以这样分类:
- 冒泡和选择排序,基于两两比较,采用递归的法:
d a t a [ n ] ≤ d a t a [ n + 1 ] data[n] \leq data[n+1] data[n]≤data[n+1]
- 快速排序,基于分治思想,采用二分法:
{ d a t a [ 0 ] . . . . d a t a [ k − 1 ] } ≤ d a t a [ k ] ≤ { d a t a [ k + 1 ] . . . . d a t a [ n ] } \{data[0] ....data[k-1] \} \leq data[k]\leq \{data[k+1] ....data[n] \} {data[0]....data[k−1]}≤data[k]≤{data[k+1]....data[n]}
数据交换
交换两个数据函数如下
int data[1000];
void swap(int *da1, int *da2)
{
int damx;
//交换数据
damx = *da1;
*da1 = *da2;
*da2 = damx;
}
冒泡排序
每次的遍历前0-n个数,将最大值放到位置n处,然后n=n-1,【两两比较递归法】
for(int i=999;i>0;i--)
{
//令data[j+1]为【0 , i】区间中的最大值
for(int j=0;j<i; j++)
{
//更新最大值到 data[j+1]
if(data[j] > data[j+1])
{
swap(&data[j], &data[j+1]);
}
}
}
选择排序
每次的遍历前0-n个数,将最大值放到位置n处,然后n=n-1,【两两比较递归法】
for(int i=999;i>0;i--)
{
int k=0;
//令k为【0 , i-1】区间中的最大值索引
for(int j=0;j<i; j++)
{
//更新最大值索引到k
if(data[j] > data[k])
{
k=j;
}
}
//更新最大值到data[i]
if(data[i] < data[k])
{
swap(&data[i], &data[k]);
}
}
快速排序
采用二分法,将数据分为左右两部分,左边部分肯定比右边部分的值小;然后再分别对两个部分进行二分操作。【二分区域递归法】
int stack[1000];//深度栈
int left = 0; //begin
int right = 999;//end
int stacp = 0;
//左右边界入栈
stack[stacp++] = left;
stack[stacp++] = right;
while (stacp != 0)
{
//取出待二分区间
int right = stack[--stacp];
int left = stack[--stacp];
//取得左右部分的划分线
int beginl = left, endr = right;
int Indata = data[beginl];//划分基准值 , 该处成为空缺的坑
int Index = beginl;//划分线索引 , 坑的位置
while (beginl < endr)//遍历区间,并跳过与基准值相等的中间部分
{
//右边的数:跳过比基准值大的,停在比基准值小处
while (beginl < endr)
{
if (data[endr] > Indata)
{
endr--;
}
else //更新基准线和基准值
{
data[Index] = data[endr];//小的数填旧坑
Index = endr;//新坑位置
beginl++;
break;
}
}
//左边的数:跳过比基准值小的,停在比基准值大处
while (beginl < endr)
{
if (data[beginl] < Indata)
{
beginl++;
}
else //更新基准线和基准值
{
data[Index] = data[beginl];//大的数填旧坑
Index = beginl;//新坑位置
endr--;
break;
}
}
}
data[Index] = Indata;//坑的值
//左右两部分区间入栈
if (Index - 1 > left)//左半部分 【left,Index】区间元素比两个多
{
stack[stacp++] = left;
stack[stacp++] = (Index - 1);
}
if (Index + 1 < right)//右半部分 【Index,right】区间元素比两个多
{
stack[stacp++] = (Index + 1);
stack[stacp++] = right;
}
}
计数排序
插入排序
插入排序建议使用链表进行操作,不推荐直接数组操作。
for(i=1; i<999; i++) //i指向无序区第一个元素
{
int da=data[i];
j=i-1;//j指向有序区第一个元素
// j往前遍历,找到比data[i]小的,插入到此处。比data[i]大的后移
while(j>=0 && da<data[j])
{
a[j+1] = a[j];
j--;
}
data[j+1] = da; //插入到空出来的位置
}