1.冒泡排序(Bubblesort)
思想:冒泡排序,是通过将一组数两两比较,每一趟会将最大或最小的数沉到最底,每一趟比较完后下一趟就会少比较一次,最后一趟完成后这组数据就会变为一组有序的数。
时间复杂度:
当一组数为有序且期望排序顺序同序时,比较次数与移动次数都达到最小值c(比较次数)=n-1,m(移动次数)= 0;
时间复杂度最小为o(n);
当一组数有序但期望排序与顺序相反时,比较次数与移动次数都达到最大值c = (n-1)+(n-2)+......+1 = n(n-1)/2 = o(n^2),m = 3n(n-1)/2 = o(n^2);
时间复杂度最大为o(n^2);
代码:
void Bubblesort(int arry[MAX_SIZE])
{
int t;
int *p = arry;
int *q = arry;
for(;p < &arry[MAX_SIZE-1];p++)
{
int i = 0;
for(q =arry;q < &arry[MAX_SIZE-i-1];q++)
{
if(*q > *(q+1))
{
t = *q;
*q = *(q+1);
*(q+1) = t;
}
}
i++;
}
}
2.选择排序(selection sort)
思想: 将一组数的第一个位置作为最小/最大数的位置(假设的),遍历整组数,找到目前最小/最大的与当前最小/最大位置(假设的)交换位置,遍历一次完成后,向后移动最小/最大数的位置(假设的),再次遍历,直到整组数有序。
时间复杂度:
第一个位置设为最小/最大位置时,若该位置数为最小/最大,且这组数为升序/降序,此时时间复杂度最小
时间复杂度最小为o(n);
第一个位置设为最小/最大位置时,若该位置数为最大/最小,且这组数为降序/升序,此时时间复杂度最大
时间复杂度最大为o(n^2);
代码:
void selectionsort(int *arry)
{
for(int i = 0 ;i < MAX_SIZE;++i)
{
int min = i;
for(int j = i;j < MAX_SIZE;++j)
{
if(arry[j] < arry[min])
{
min = j;
}
}
if(min != i)
{
int t = arry[min];
arry[min] = arry[i];
arry[i] = t;
}
}
}
3.插入排序(insertionsort)
思想:将一组数分为两种,有序与无序,开始时将第一个元素看为有序部分,然后将后面紧连着的无序部分的第一个数与前面有序部分比较,插入到有序部分,并且保持有序部分的有序。然后用与前面一样的方法将无序部分的元素挨个插入到有序部分,最后使整组数完全有序。
时间复杂度:
当一开始整组数为有序,且升序或降序的期望与顺序相同时,时间复杂度最小;
时间复杂度最小为o(n);
当整组数有序时,但升序或降序的期望与顺序相反时,时间复杂度最高;
时间复杂度最高为o(n^2);
void insertionsort(int *arry)
{
int i = 1, j = 0;
int t = 0;
for(i;i < MAX_SIZE;++i)
{
t = arry[i]; //将要插入的数放入临时容器t中
j = i-1; //j为有序部分的最后一个元素的下标
while(j >= 0 && t < arry[j])//找到将要插入的数的位置
{
arry[j+1] = arry[j];//将有序元素往后移
j--;
}
arry[j+1] = t;//将要插入的元素插入
}
}
4.希尔排序(shellsort)
思想:希尔排序主要用了分治的思想,引入步长的概念提高插入排序的效率,对于一组数,规定步长将符合步长的多个数用插入排序进行排序,再重新组合起来,然后缩短步长再次排序,当步长为1时整组数的无序性很低,再次插入排序后就得到了有序的一组数。
时间复杂度:
希尔排序的时间复杂度与步长的选取有关,步长与时间复杂度对应关系如下:
希尔增量(n/2) 时间复杂度:o(n^2)
hibbard增量{2*k-1,......,7,3,1} 时间复杂度:0(n^(3/2))
最小的时间复杂度:o(n*log2n)
代码:
void shellsort(int v[])//希尔增量
{
int gap,i,j,temp;
for (gap = MAX_SIZE/2; gap > 0; gap /= 2)
{
for(i = gap; i < MAX_SIZE; i++)
for(j = i-gap; j>=0 && v[j]>v[j+gap]; j -= gap)
{
temp = v[j];
v[j] = v[j+gap];
v[j+gap] = temp;
}
}
}
5.快速排序(quicksort)
思想:开始时随意找数组中的某个数作为"基准数",然后按照(从右往左)再(从左往右)的顺序依次寻找比基准数(小)和比基准数(大)的,数,如果没有相遇,就将两个数相互交换,直到两个数相遇,再将此时的数与基准数交换位置,这时基准数左边的数都是比基准数小的,右边都是比基准数大的。然后对基准数左右分别进行快排,如此循环,最后整组数就排序完成了。
时间复杂度:
最坏情况下为o(n^2);
最好情况下为:o(n*log2n);
代码:
void quicksort(int left,int right)
{
int i,j,t,temp;
if(left > right)
{
return;
}
temp = a[left];
i = left;
j = right;
while(i !=j)
{
while(a[j]>temp && i<j)
{
j--;
}
while(a[i]>temp && i<j)
{
i++;
}
if(i<j)
{
t=a[i];
a[i] = a[j];
a[j] = t;
}
}
a[left] = a[i];
a[i] = temp;
quicksort(left,i-1);
quicksort(i+1,right);
}