【蓝蓝计算机考研算法】-day26-折半查找的递归算法&&快排

142 阅读2分钟

39、折半查找的递归算法

思路

根据查找的起始位置和终止位置,将查找序列一分为二,判断所查找的关键字在哪一部分,然后用新的序列的起始位置和终止位置递归求解。

  • 输入数组元素,元素必须有序。输入要查找的元素。

  • 定义折半查找的递归函数,传入参数有:数组,查找元素,左端点下标,右端点下标。

  • 当左端点下标大于右端点时,退出递归,表示查找失败。否则,定义中间变量的下标mid,当查找元素x等于a[mid]时,表示找到了该元素,返回下标mid;当查找元素x>a[mid]时,表示该元素在区间右半段,所以继续递归,左右区间端点分别为mid+1、right;当查找元素x<a[mid]时,表示该元素在区间左半段,因此继续递归,左右区间端点分别为left、 mid-1。

具体实现

#include <stdio.h>
typedef int ElemType;
/*
//定义为SSTable,则就写ST.elem[mid]
typedef struct {
    ElemType* elem;     //存储空间基址,建表时按实际长度分配,0好留空
    int length;         //表的长度
}SSTable;
*/
//递归实现折半查找
int BinSearch(int ST[], ElemType key, int low, int high) {
    if (low > high) {
        return 0;
    }
    int mid = (low + high) / 2; //取中间位置
    if (key >ST[mid]) {   //向后半部查找 定义为SSTable,则就写ST.elem[mid]
        BinSearch(ST, key, mid + 1, high);
    }
    else if(key< ST[mid])   //向前半部查找
    {
        BinSearch(ST, key, low, mid-1);
    }
    else
    {
        return mid;
    }
}
int main()
{
    int a[100], n = 0, x, b;
    while (scanf_s("%d",&b) ) { //输入数组元素,必须有序 
        a[n++] = b;
        if (getchar() == '\n') 
            break;
    }
    printf("输入要查找的数:");
    scanf_s("%d",&x); //输入要查找的数 

    int f = BinSearch(a, x, 0, n - 1); //调用折半查找
    if (f == -1) printf( "不在数组中");
    else printf( "下标为:%d" , f);
    return 0;
}

运行结果

image.png

复杂度

  • 时间复杂度O(logn) ---把规模为n的复杂问题,经过多次递归转化为规模减半的子问题求解
  • 空间复杂度 O(logn) --- 用到一个递归工作栈,其规模与递归深度有关

40、快速排序。

思路

  • 在待排序的数组中,首先找一个数字作为基准数,为了方便,一般选第一个数作为基准数key。

  • 把待排序的数列中小于key的元素移到左边,大于key的元素移到右边,此时,左右两个分区的元素就相对有序了。

  • 接着把两个分区的元素分别按照上面两种方法继续对每个分区找出基准数key,然后移动,直到各个分区只有一个数时为止。

具体实现

/快速排序
#include<stdio.h>

void QuickSort(int a[], int left, int right) {
	if (left < right) { //不加会陷入死循环 
		int i = left, j = right;
		int key = a[left];

		while (i < j) {
			while (i<j && a[j]>key)
				j--;
			if (i < j) //右半段的数比key小
				a[i++] = a[j]; //先赋值再自增 

			while (i < j && a[i] < key)
				i++;
			if (i < j) //左半段的数比key大 
				a[j--] = a[i]; //先赋值再递减 
		}

		a[i] = key;
		QuickSort(a, left, i - 1); //给左边排序
		QuickSort(a, i + 1, right); //给右边排序 
	}
}
int main() {
	int a[100], n = 0, b;
	while (scanf_s("%d",&b) ) { //输入数组元素
		a[n++] = b;
		if (getchar() == '\n') 
			break;
	}

	QuickSort(a, 0, n - 1); //快排函数 

	for (int i = 0; i < n; i++) //输出排序后的数组元素 
		printf("%d ", a[i]) ;
	return 0;
}

运行结果

image.png

复杂度

  • 时间复杂度O(n^2) ---与划分是否对称无关,是发生在两个区域分别包含n-1个元素和0个元素时
  • 空间复杂度 O(logn) --- 用到一个递归工作栈,其规模与调用的最大深度一致

快排优化

快排的优化方法,未运行成功,也无报错!!!!
时间O(nlogn) 空间O(logn)

//优化方法-快排
#include <stdlib.h>
#include<stdio.h>
void swap(int a, int b) {//交换两元素
	int temp = 0;
	temp = a;
	a = b;
	b = temp;
}
void QuickSort(int a[], int left, int right) {
	if (left >= right) {
		return;
	}
	int pivot, i = left, j = right;//pivot是枢轴,i指向最左边,j指向最右边
	int m = i + rand() % (j - i + 1);//实现左边数与右边数的随机数
	swap(a[left], a[m]);//m是left与right之间的随机函数
	pivot = a[left];//pivot指向左边,参与比较
	while (i < j) {
		while (i<j&&a[j]>pivot)
		{
			j--;
		}while (i<j&&a[i]<=pivot)
		{
			i++;
		}
		if (i < j) {
			swap(a[i], a[i]);
		}
	}
	swap(a[left], a[i]);
	QuickSort(a, left, i - 1);//递归处理左区间
	QuickSort(a, i + 1, right);//递归处理右区间

}
int main() {
	int a[100], n = 0, b;
	while (scanf_s("%d",&b) ) { //输入数组元素
		a[n++] = b;
		if (getchar() == '\n') 
			break;
	}
	printf("输入成功 ");
	QuickSort(a, 0, n - 1); //快排函数 

	for (int i = 0; i < n; i++) //输出排序后的数组元素 
		printf("%d ", a[i]) ;
	return 0;
}

1.rand()介绍:

  1. rand()是C语言系统函数,用来生成随机数,使用前要包含头文件"stdlib.h"(<stdlib.h>)。
  2. rand()是一个无参函数
  3. 单纯调用rand(),会随机生成0~很大一个整数,之间的任意整数。
  4. 使用rand()表达式生成指定范围内的随机数:
    rand()%n;表示生成0-n-1的随机整数。
    例如:rand()%10;表示生成0~9的随机整数。

4. 生成n~m的随机整数的表达式:n+rand()%(m-n+1);(n<m)。