常用排序算法总结

在面试或者数据结构相关的考试中,经常会被要求到的算法主要有插入排序、冒泡排序、归并排序和快速排序。对这几种算法,不但应该知道其原理或者过程,还应该对他们的各种特性了然于胸,从最好、最差、平均时间空间复杂度等方面对比其优劣。在面试中这几种排序算法也会经常作为手写代码能力的考量,所以应该要求自己对这几种算法的代码信手拈来。所以在此把几种算法详细记录一下。

冒泡排序

/***********冒泡排序************
空间复杂度:O(1)
时间复杂度:有序的时候最好情况为O(n),最坏和平均为O(n^2)
稳定性:稳定
*/
void bubbleSort(int *arr, int n){
	for(int i = 1; i<n; i++){
		int j = i-1;
		while(j>=0){
			if(arr[j] > arr[j+1]){
				int tmp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = tmp;
				j--;
			}
			else break;//本趟遍历没有发生交换
		}
	}
}

快排

//http://blog.csdn.net/morewindows/article/details/6684558 挖坑排序
void quick_sort(int s[], int l, int r)  
{  
    if (l < r)  
    {  
        
        int i = l, j = r, x = s[l];  
        while (i < j)  
        {  
            while(i < j && s[j] >= x) // 从右向左找第一个小于x的数  
                j--;    
            if(i < j)   
                s[i++] = s[j];  
              
            while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数  
                i++;    
            if(i < j)   
                s[j--] = s[i];  
        }  
        s[i] = x;  
        quick_sort(s, l, i - 1); // 递归调用   
        quick_sort(s, i + 1, r);  
    }  
}  

插入排序

/***********折半插入排序*************
相对于直接插入排序,它在查找的时候用
折半查找,减少了比较的次数,但是移动
的次数不变,还是n平方
空间复杂度:O(1)
时间复杂度:O(n^2)
稳定性:稳定
************************************/
void insertSortBi(int *arr, int n){
	int i, j, low, mid, high;
	for(i = 2; i<=n; i++){
		arr[0] = arr[i];//arr[0]为哨兵,不存放元素
		low = 1; high = i-1;		
		//折半查找,减少了比较次数
		while(low <= high){
			mid = (low+high)/2;
			if(arr[mid] > arr[0]) high = mid-1;
			else low = mid + 1;
		}

		//向后移动元素
		for(j = i-1; j>=high+1; --j)
			arr[j+1] = arr[j];
		
		arr[high+1] = arr[0];
	}

	//打印元素
	//for(int k = 0; k<6; k++)
		//cout<<arr[k]<<endl;
}

堆排序

//从i节点开始调整,从0开始计数,len为节点总数
void MinHeapFixdown(int a[], int i, int n)  
{  
    int j, temp;  
  
    temp = a[i];  
    j = 2 * i + 1;  
    while (j < n)  
    {  
        if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的  
            j++;  
  
        if (a[j] >= temp)  
            break;  
  
        a[i] = a[j];     //把较小的子结点往上移动,替换它的父结点  
        i = j;  
        j = 2 * i + 1;  
    }  
    a[i] = temp;  
} 

//构建小根堆
void buildMinHeap(int arr[], int len)
{
	for(int i = len/2-1; i>=0; i--)
		//把第i个元素向下调整(如果大于子节点的话)
		MinHeapFixdown(arr, i, len);
}

/***********堆排序*******
堆排序需要先对线性表中的元素构建堆,然后根据堆的性质,
输出堆顶元素,然后对输出堆顶后被破坏的堆重新调整为堆,
如此重复,直到堆中仅剩下一个元素位置
空间复杂度:O(1)
时间复杂度:最好最坏和平均情况下都为O(nlogn)
稳定性:不稳定
*/
void heapSort(int arr[], int n)
{
	//构建小根堆,小根堆的排序后是从大到小的顺序
	buildMinHeap(arr, n);
	for(int i = n-1; i>0; i--){
		swap(arr[i], arr[0]);
		MinHeapFixdown(arr, 0, i);
	}
}
posted @ 2017-03-16 10:12  木白的菜园  阅读(202)  评论(0编辑  收藏  举报