一、快速排序
基本思想:
1)选择一个基准元素,通常选择第一个元素或者最后一个元素。
2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。
3)此时基准元素在其排好序后的正确位置。
4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
代码实现:
void quick_sort(int a[], int s, int t)
{
int i=s,j=t;
int tmp = 0;
if(s < t)
{
tmp=a[s];
while(i != j)
{
while(j > i && a[j] >= tmp)
j--;
a[i] = a[j];
while(i < j && a[i] <= tmp)
i++;
a[j] = a[i];
}
a[i] = tmp;
print_arr(a);
quick_sort(a, s, i-1);
quick_sort(a, i+1, t);
}
}
非递归实现:
int partition(int a[],int low,int high){
int pivot=a[low]; //任选元素作为轴,这里选首元素
while(low<high){
while(low<high && a[high]>=pivot)
high--;
a[low]=a[high];
while(low<high && a[low]<=pivot)
low++;
a[high]=a[low];
}
//此时low==high
a[low]=pivot;
return low;
}
/**使用栈的非递归快速排序**/
void quicksort2(int a[],int low,int high){
stack<int> st;
if(low<high){
int mid=partition(a,low,high);
if(low<mid-1){
st.push(low);
st.push(mid-1);
}
if(mid+1<high){
st.push(mid+1);
st.push(high);
}
//其实就是用栈保存每一个待排序子串的首尾元素下标,下一次while循环时取出这个范围,对这段子序列进行partition操作
while(!st.empty()){
int q=st.top();
st.pop();
int p=st.top();
st.pop();
mid=partition(a,p,q);
if(p<mid-1){
st.push(p);
st.push(mid-1);
}
if(mid+1<q){
st.push(mid+1);
st.push(q);
}
}
}
}
二、冒泡排序
基本思想:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
代码实现:
void bubble_sort(int a[], int len)
{
int i,j;
int tmp;
short flag = 0;
for(i = 0;i < len - 1;i++)
{
flag=0;
for(j=len-1;j>i;j--)
{
if(a[j] < a[j-1])
{
tmp = a[j];
a[j] = a[j-1];
a[j-1] = tmp;
flag=1;
}
}
print_arr(a);
if(0 == flag)
{
return;
}
}
}
三、选择排序
基本思想:
在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
代码实现:
void select_sort(int a[], int len)
{
int i,j,k;
int tmp;
for(i = 0;i < len-1; i++)
{
k = i;
for(j = i+1;j < len; j++)
{
if(a[j] < a[k])
k=j;
if(k !=i )
{
tmp = a[i];
a[i] = a[k];
a[k] = tmp;
}
}
print_arr(a);
}
}
四、希尔排序
基本思想:
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。操作方法:
1)选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
2)按增量序列个数k,对序列进行k 趟排序;
3)每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
代码实现:
void shell_sort(int a[], int n)
{
int i,j, gap;
int tmp;
gap = n/2;
while(gap > 0)
{
for(i = gap;i < n;i++)
{
tmp = a[i];
j = i - gap;
while(i >= 0 && tmp < a[j])
{
a[j+gap] = a[j];
j = j - gap;
}
a[j+gap] = tmp;
}
gap = gap/2;
print_arr(a);
}
}
五、直接插入排序
基本思想:
将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
要点:设立哨兵,作为临时存储和判断数组边界之用。
代码实现:
void insert_sort(int a[], int n)
{
int i,j;
int tmp;
for(i = 1;i < n;i++)
{
if(a[i] < a[i-1])
{
j = i - 1;
tmp = a[i];
a[i] = a[i-1];
while(tmp < a[j])
{
a[j+1] = a[j];
j--;
}
a[j+1] = tmp;
}
print_arr(a);
}
}