2017.01.09:排序与搜索

排序和搜索

1.所谓的内排序是指所有的数据已经读入内存。在内存中进行排序的算法;同时,内排序也一般假定所有用到的辅助空间可以直接存在于内存中。与之对应,另一类排序称为外排序,即内存中无法保存全部数据,需要进行磁盘访问,每次读入部分数据到内存进行排序。

 

合并排序:利用分而治之的思想,对两部分非别进行排序,排序完成后,在将各自排序好的两个部分合并还原成一个有序结构;算法的时间复杂度为O(nlog n)。

 //合并函数
void Merge(int *_Array, int p, int q, int r) {// p:第0个;r:第n-1个数,q:第(r + p) / 2个数 
    int len1 = q - p + 1;
    int len2 = r - q;
    int *L = new int[len1 + 1];//用动态数组储存左边的数 
    int *R = new int[len2 + 1];//用动态数组储存右边的数 

    for (int i = 0; i < len1; i++) {// 把Array数组左边的数放入L数组 
        L[i] = _Array[p + i];
    }

    for (int j = 0; j < len2; j++) {// 把Array数组右边的数放入R数组 
        R[j] = _Array[q + 1 + j];
    }
    L[len1]=R[len2]=INT_MAX;    //定义无穷大 
    int i = 0, j = 0;
    for (int k = p; k <= r; k++) {
        if (L[i] < R[j]) {//小的放左边,大的放右边 
            _Array[k] = L[i];
            i++;
        }
        else {
            _Array[k] = R[j];
            j++;
        }
    }
}
//  归并排序
void MergeSort(int _Array[], int p, int r) {
    if (p < r) {//p:第0个;r:第n-1个数。数组至少要有两个数据 
        int q;
        q = (r + p) / 2;//拆分两组 
        MergeSort(_Array , p , q);//拆分第0个到第 (r + p) / 2个 ,即拆分左半部分 
        MergeSort(_Array , q+1 , r);//拆分第(r + p) / 2个到第r个 ,即拆分右半部分 
        Merge(_Array , p , q , r);//调用合并函数,从第0个到第n-1个排好 
    }
}

快速排序:随机选定一个元素作为轴值,利用该轴值将数据分为左右两个部分,左边元素都比轴值小,右边元素都比轴值大,但他们不是完全排序的,在此基础上,分别对左右两堆递归调用快速排序。算法的时间复杂度为O(nlog n),在最坏的情况下为O(n^2),额外空间复杂度O(log n)。


//快速排序
void quick_sort(int s[], int l, int r)
{
    if (l < r)
    {
		//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
        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);
    }
}

堆排序:每次将剩余的最大元素移动到数组的最右边。算法的时间复杂度为O(nlog n),空间复杂度O(1)。

//堆排序函数
void HeapSort(int a[],int length)
{
    int temp;
    BuildMaxHeap(a,length);
    for (int i = length - 1; i >= 1; i--)
    {
        //交换根节点和数组的最后一个节点
        temp = a[i];
        a[i] = a[0];
        a[0] = temp;
        MaxHeapify(a, 0, 0, i-1);//维护从下标为i-1到0的子数组
    }
}

桶排序和基数排序:不需要进行数据之间的两辆比较,但是需要事先知道数组的一些具体情况。桶排序适用于知道待排序数组大小范围的情况,其特性在于将数据根据其大小,放入合适的桶中,再依次从桶中取出,形成有序序列。基数排序,进行了K次桶排序。

void radixsort(int data[], int n) //基数排序  
{  
    int d = maxbit(data, n);  
    int tmp[n];  
    int count[10]; //计数器  
    int i, j, k;  
    int radix = 1;  
    for(i = 1; i <= d; i++) //进行d次排序  
    {  
        for(j = 0; j < 10; j++)  
            count[j] = 0; //每次分配前清空计数器  
        for(j = 0; j < n; j++)  
        {  
            k = (data[j] / radix) % 10; //统计每个桶中的记录数  
            count[k]++;  
        }  
        for(j = 1; j < 10; j++)  
            count[j] = count[j - 1] + count[j]; //将tmp中的位置依次分配给每个桶  
        for(j = n - 1; j >= 0; j--) //将所有桶中记录依次收集到tmp中  
        {  
            k = (data[j] / radix) % 10;  
            tmp[count[k] - 1] = data[j];  
            count[k]--;  
        }  
        for(j = 0; j < n; j++) //将临时数组的内容复制到data中  
            data[j] = tmp[j];  
        radix = radix * 10;  
    }  
}  


快速选择算法:利用快速排序的思想,时间复杂度是O(n)。

二分查找:算法复杂度为O(logn)。

 int binarySearch(int *array, int left, int right, int value){
	 if(left>right){
		 return -1;
	 }
	 
	 int mid = right - (right - left)/2;
	 if(array[mid] == value){
		 return mid;
	 } else if(array[mid] < value){
		 return binarySearch(array,mid+1,right, value);
	 } else {
		 return binarySearch(array, left, mid-1, value);
	 }
 }




发布了50 篇原创文章 · 获赞 6 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章