这几天看了郝斌的数据结构视频,对于各种排序方式有了更深刻的理解。下面与大家分享下我的学习成果,不足之处忘指正。

    PS:博文中的代码都是自己敲的,便于理解。

    这里讲的五种排序方式,是指冒泡排序、直接选择排序、直接插入排序、快速排序以及二路归并排序。

    冒泡排序:排序的思路正如“冒泡”二字,每次比较第i和i+1个位置的值,若a[i]>a[i+1],则交换。这样第一趟下来,最大的数在第n-1个位置;第二趟下来,次最大的数在第n-2个位置,依此类推,直到所有的数排序完毕。

    C语言的代码为(p指向数组首元素,len表示数组元素的个数):   

void bubbleSort(int *p, int len)
{
int i = 0;
int j = 0;
int temp = 0;
for (i = 0; i < len-1; i++)
{
for (j = 0; j < len-1-i; j++)
{
if (p[j] > p[j+1])
{
temp = p[j];
p[j] = p[j+1];
p[j+1] = temp;
}
}
}
}

    冒泡排序是稳定的,平均时间复杂度为o(n2)

    直接选择排序。若是从小到大排序,则第1趟把最小的值放在第0个位置,第2趟把次最小值放在第1个位置,依此类推,直到所有的数排序完毕。

    c语言代码为:

void selectSort(int *p, int len)
{
int i = 0;
int j = 0;
int temp = 0;
for (i = 0; i < len; i++)
{
for (j = i+1; j < len; j++)
{
if (p[j] < p[i])
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
}

     直接选择排序是不稳定的算法,平均时间复杂度也是o(n2)。看到网上很有人认为选择排序是稳定的算法,其实不然,例如5,3,5,2,1。第一趟排序完后,第一个5与最后的1交换,位置为2的5自然在原本位置为0的5的前面了。

     直接插入排序。假定前i个数已经有序,直接插入排序是把第i+1个数插入到前i个数中的合适位置,重新组成大小为i+1个数的有序序列。

    C语言实现代码:

void insertSort(int *p,int len)
{
int i = 0;
int j = 0;
int temp = 0;
for (i = 1; i < len; i++)
{
temp=p[i];
for (j = i; j > 0 && temp < p[j-1]; j--)
{
p[j] = p[j-1];
}
p[j] = temp;
}
return;
}

    直接插入排序是稳定的,平均时间复杂度也是o(n2)。

    快速排序。快速排序采用递归思想,速度自然快很多。假定有n个数,参考值value,也就是我们的比较对象为数组的第一个元素,那么一趟快速排序后,value左侧的值都比value小,右侧的值都比value大。然后再按此方法对这两部分数据分别进行快速排序,依此类推,直到整个数据变成有序序列。

    C语言代码如下:

void quickSort(int *p,int low ,int high)
{
int posi = 0;
if (high > low)
{
posi = findPosi(p,low,high);
if (posi > low){
quickSort(p,low,posi-1);
}
if (posi < high){
quickSort(p,posi+1,high);
}
}
}
int findPosi(int *p,int low,int high)
{
int value = *(p+low);
while (high > low)
{
while(p[high] >= value && high > low)
{
high--;
}
p[low] = p[high];
while (p[low] <= value && low < high)
{
low ++;
}
p[high] = p[low];
}
p[low] = value;
return low;
}

    快速排序是不稳定的,平均时间复杂度是o(log2n)。

    最后是归并排序。二路归并排序的思想是分而治之,即divide and conquer。divide:不断地拆分数组,直到每个数组都只有一个元素。conquer:并,把拆分后的数组按关键字排序,不断合并,直到整个数据有序。很明显,二路归并排序利用了递归的思想。

    下面给出它的C语言实现:

void divide(int *p,int low,int high){
int mid = (low + high)/2;
if (low < high){
divide(p,low,mid);
divide(p,mid+1,high);
}
GuiBingSort(p,low,mid,high);
}
void GuiBingSort(int *p,int low,int mid, int high){
int leftIndex = low;
int rightIndex = mid+1;
int tempIndex = 0;
int tempLen = high-low+1;
int *temp = (int *)malloc(sizeof(int)*(tempLen));
if (NULL == temp){
printf("分配内存失败!\n");
return;
}
while(leftIndex <= mid && rightIndex <= high){
if (p[leftIndex] <= p[rightIndex]){
temp[tempIndex] = p[leftIndex];
leftIndex++;
}else{
temp[tempIndex] = p[rightIndex];
rightIndex++;
}
tempIndex++;
}
if (leftIndex > mid){
while(rightIndex <= high){
temp[tempIndex] = p[rightIndex];
rightIndex++;
tempIndex++;
}
}else if (rightIndex > high){
while (leftIndex <= mid){
temp[tempIndex] = p[leftIndex];
leftIndex++;
tempIndex++;
}
}
int i = 0;
for (i = 0; i < tempLen; i++ ){
p[i+low] = temp[i];
}
free(temp);
return;
}

    归并排序是稳定的,平均时间复杂度是o(log2n)。

    最后附上main函数的代码:

int main()
{
int a[7] = {1,5,4,89,23,100,-3};
int len = sizeof(a)/sizeof(int);
// printf("插入排序之后\n");
//insertSort(a,len);
showArray(a,len);
// printf("选择排序之后\n");
// selectSort(a,len);
showArray(a,len);
// printf("冒泡排序之后:\n");
//bubbleSort(a,len);
showArray(a,len);
// printf("快速排序之后\n");
// quickSort(a,0,len-1);
showArray(a,len);
printf("归并排序之后\n");
divide(a,0,len-1);
showArray(a,len);
return 0;
}