C语言各种查找算法实现(二分查找、三分查找、顺序查找、插值查找、寻找第k小元素)


1- 生成数组

能够人工输入或随机生成一个长度为n的整数数组,要求数组任意两个元素都互不相同。

(1)手动生成数组

#include <stdio.h>
#include <stdlib.h>

void manual_array();   /*手动输入数组*/                        

int size;
int a[512];

int main(int argc, char *argv[])
{
    manual_array();

    return 0;
}


/*手动输入数组*/
void manual_array()
{
    printf("Please enter the build array size:");
    scanf("%d\n", &size);
    for (int i = 0; i < size; i++)
    {
        scanf("%d", &a[i]);
        for (int j = 0; j < i; j++)
        {
            while (a[i] == a[j])
            {
                printf("ERROR: Duplicate input data.Please try again\n");
                j = 0;
                scanf("%d\n", &a[i]);
            }
        }
    }

    printf("Array[%d]:", size);
    for (int i = 0; i < size; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

在这里插入图片描述

(2)自动生成数组

#include <stdio.h>
#include <stdlib.h>

void random_array();   /*自动生成数组*/                        

int size;
int a[512];

int main(int argc, char *argv[])
{
    random_array();

    return 0;
}


/*自动生成数组*/
void random_array()
{
    printf("Please enter the build array size:");
    scanf("%d", &size);
    int i, j, x;
    for (i = 0; i < size; i++)
    {
        x = rand() % 1000;
        for (j = 0; j < i; j++)
        {
            while (x == a[j])
            {
                x = rand() % 1000;
                j = 0;
            }
        }
        a[i] = x;
    }
    printf("Array[%d]:\n", size);
    for (i = 0; i < size; i++)
    {
        printf("%-3d ", a[i]);
    }
    printf("\n");
}

在这里插入图片描述


2- 判断升降(判断先升后降 先降后升 升序 降序 乱序)

#include <stdio.h>
#include <stdlib.h>

void manual_array();                   /*手动输入数组*/     
void Judge_array(int *array, int size);/*判断升序降序还是先升后降还是先降后升*/                  
int size;
int a[512];

int main(int argc, char *argv[])
{
    manual_array();
    Judge_array(a, size);
    return 0;
}


/*手动输入数组*/
void manual_array()
{
    printf("Please enter the build array size:");
    scanf("%d\n", &size);
    for (int i = 0; i < size; i++)
    {
        scanf("%d", &a[i]);
        for (int j = 0; j < i; j++)
        {
            while (a[i] == a[j])
            {
                printf("ERROR: Duplicate input data.Please try again\n");
                j = 0;
                scanf("%d\n", &a[i]);
            }
        }
    }

    printf("Array[%d]:", size);
    for (int i = 0; i < size; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

/*判断升序降序还是先升后降还是先降后升*/
void Judge_array(int *array, int size)
{
    int a = 1, d = 1, a_d = 0, d_a = 0;
    int min_i, max_i;
    int max = array[0], min = array[0];

    /*get min and max*/
    for (int i = 0; i < size; i++)
    {
        if (array[i] > max)
        {
            max = array[i];
        }
        if (array[i] < min)
        {
            min = array[i];
        }
    }
    /*get min_i and max_i*/
    for (int i = 0; i < size; i++)
    {
        if (array[i] == max)
        {
            max_i = i;
        }
        if (array[i] == min)
        {
            min_i = i;
        }
    }

    /*judge fall and rise*/
    for (int i = 0; i < size - 1; i++)
    {
        if (array[i + 1] > array[i])
        {
            a++;
        }

        if (array[i + 1] < array[i])
        {
            d++;
        }
    }

    /*The judgment goes up before it goes down*/
    for (int i = 0; i < max_i; i++)
    {
        if (max_i != 0 && max_i != size - 1)
        {
            if (array[i + 1] > array[i])
            {
                a_d++;
            }
        }
    }
    for (int i = max_i + 1; i < size - 1; i++)
    {
        if (max_i != 0 && max_i != size - 1)
        {
            if (array[i] > array[i + 1])
            {
                a_d++;
            }
        }
    }

    /*Judgments go down before they go up*/
    for (int i = 0; i < min_i; i++)
    {
        if (min_i != 0 && min_i != size - 1)
        {
            if (array[i + 1] < array[i])
            {
                d_a++;
            }
        }
    }

    for (int i = min_i + 1; i < size - 1; i++)
    {
        if (min_i != 0 && min_i != size - 1)
        {
            if (array[i] < array[i + 1])
            {
                d_a++;
            }
        }
    }

    if (a == size)
    {
        printf("Ascending sort: 1\n");
    }
    else if (d == size)
    {
        printf("Descending sort: 2\n");
    }
    else if (a_d == size - 2)
    {
        printf("First rise then descend: 3\n");
    }
    else if (d_a == size - 2)
    {
        printf("First fall after rise: 4\n");
    }
    else
    {
        printf("Random sequence: 0\n");
    }
}

在这里插入图片描述


3- 顺序查找

等于算是暴力解答吧。顺序查找具体元素。
首先自动生成一组序列,然后查找,返回下标以及值,以及比较次数。
如果想用手动输入的话就用标题一的代码。

#include <stdio.h>
#include <stdlib.h>

void random_array();   /*自动生成数组*/  
void Sequential_search_violence(int *a, int value, int size);   /*顺序查找*/                  
int size;
int a[512];

int main(int argc, char *argv[])
{
    int key;
    random_array();

    printf("Please enter the number you want to find:");
    scanf("%d", &key);

    Sequential_search_violence(a, key, size);

    return 0;
}


/*自动生成数组*/
void random_array()
{
    printf("Please enter the build array size:");
    scanf("%d", &size);
    int i, j, x;
    for (i = 0; i < size; i++)
    {
        x = rand() % 1000;
        for (j = 0; j < i; j++)
        {
            while (x == a[j])
            {
                x = rand() % 1000;
                j = 0;
            }
        }
        a[i] = x;
    }
    printf("Array[%d]:\n", size);
    for (i = 0; i < size; i++)
    {
        printf("%-3d ", a[i]);
    }
    printf("\n");
}

/*顺序查找*/
void Sequential_search_violence(int *a, int value, int size)
{
    int rv = 0;
    int time = 0;

    for (int i = 0; i < size; i++)
    {
        time++;
        if (value == a[i])
        {
            printf("Sequential_search:     array[%d]:%d     time:%d\n", i, value, time);
            rv = 1;
        }
    }
    if (rv == 0)
    {
        printf("Not find 1\n");
    }
}

在这里插入图片描述


4- 二分查找

(1)二分查找(单调序列)

二分查找查找升序或者降序中的具体元素。
二分查找的前提就是有序序列,这里升序降序都是可以的。

#include <stdio.h>
#include <stdlib.h>

void manual_array();                             /*手动输入数组*/     
void binary_search(int *arr, int key, int sz);   /*二分法查找(升序降序都可)*/           
int size;
int a[512];

int main(int argc, char *argv[])
{
    int key;
    manual_array();

    printf("Please enter the number you want to find:");
    scanf("%d", &key);

    binary_search(a, key, size);
    return 0;
}


/*手动输入数组*/
void manual_array()
{
    printf("Please enter the build array size:");
    scanf("%d\n", &size);
    for (int i = 0; i < size; i++)
    {
        scanf("%d", &a[i]);
        for (int j = 0; j < i; j++)
        {
            while (a[i] == a[j])
            {
                printf("ERROR: Duplicate input data.Please try again\n");
                j = 0;
                scanf("%d\n", &a[i]);
            }
        }
    }

    printf("Array[%d]:", size);
    for (int i = 0; i < size; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

/*[2]二分法查找(升序降序都可)*/
void binary_search(int *arr, int key, int sz)
{
    printf("\n");
    int left = 0;       //左边
    int right = sz - 1; //右边
    int mid;
    int min_key = -1;
    int min_key_i;
    int time = 0;
    if (arr[0] < arr[1])
    {
        /*升序*/
        while (left <= right)
        {
            time++;
            mid = (right + left) / 2;
            //说明key在arr[mid]和left之间
            if (arr[mid] > key)
            {
                right = mid - 1;
            }
            //说明key在arr[mid]和right之间
            else if (arr[mid] < key)
            {
                left = mid + 1;
            }
            else
            {
                printf("Binary_search:         array[%d]:%d     time:%d\n", mid, key, time);
                break;
            }
        }
    }
    if (left > right)
    {
        time++;
        for (int i = 0; i < sz; i++)
        {
            if (arr[i] < key)
            {
                min_key = arr[i];
                min_key_i = i;
            }
        }
        printf("Binary_search:         array[%d]:%d     time:%d\n", min_key_i, min_key, time);
    }

    /*降序*/
    left = 0;
    right = sz - 1; //右边
    if (arr[0] > arr[1])
    {
        while (left <= right)
        {
            time++;
            mid = (right + left) / 2;
            //说明key在arr[mid]和right之间
            if (arr[mid] > key)
            {
                left = mid + 1;
            }
            //说明key在arr[mid]和left之间
            else if (arr[mid] < key)
            {
                right = mid - 1;
            }
            else
            {
                printf("Binary_search:         array[%d]:%d     time:%d\n", mid, key, time);
                break;
            }
        }
    }
    if (left > right)
    {
        time++;
        for (int i = 0; i < sz; i++)
        {
            if (arr[i] < key && min_key == -1)
            {
                min_key = arr[i];
                min_key_i = i;
            }
        }
        printf("Binary_search:         array[%d]:%d     time:%d\n", min_key_i, min_key, time);
    }
}

在这里插入图片描述

(2)二分查找(先升后降序列)

#include <stdio.h>
#include <stdlib.h>

void manual_array();                             /*手动输入数组*/     
int  process(int *a, int L, int R);               /*[5]二分查找(先升后降)*/
int  size;
int  a[512];

int main(int argc, char *argv[])
{
    manual_array();

    int max = process(a, 0, size-1);
    printf("Max: %d\n", max);

    return 0;
}
/*手动输入数组*/
void manual_array()
{
    printf("Please enter the build array size:");
    scanf("%d\n", &size);
    for (int i = 0; i < size; i++)
    {
        scanf("%d", &a[i]);
        for (int j = 0; j < i; j++)
        {
            while (a[i] == a[j])
            {
                printf("ERROR: Duplicate input data.Please try again\n");
                j = 0;
                scanf("%d\n", &a[i]);
            }
        }
    }

    printf("Array[%d]:", size);
    for (int i = 0; i < size; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

/*[5]二分查找(先升后降)*/
int process(int *a, int L, int R)
{
    // L是该段数据的左边界
    // R是该段数据的右边界
    if (L == R)
    {
        return *(a + L);
    }
    int mid = L + ((R - L) / 2); //计算中点
    int Leftmax = process(a, L, mid);
    int Rightmax = process(a, mid + 1, R);
    return (Leftmax > Rightmax) ? Leftmax : Rightmax;
}

在这里插入图片描述


5- 插值查找

插值查找法又叫做插补查找法,是二分查找法的改进版。它是按照数据位置的分布,利用公式预测数据所在的位置,再以二分法的方式渐渐逼近。使用插值法是假设数据平均分布在数组中,而每一项的差距相当接近或有一定的距离比例。插值法的公式为:

Mid = low + ((key - data[low]) / (data[high] - data[low])) * (high - low)

总的来说就是将上面的二分查找中的mid算法换成这个公式就可以了,其他的不变。

#include <stdio.h>
#include <stdlib.h>

void manual_array();                             /*手动输入数组*/     
void Interpolation_search(int *arr, int key, int sz);   /*二分法查找(升序降序都可)*/           
int size;
int a[512];

int main(int argc, char *argv[])
{
    int key;
    manual_array();

    printf("Please enter the number you want to find:");
    scanf("%d", &key);

    Interpolation_search(a, key, size);
    return 0;
}


/*手动输入数组*/
void manual_array()
{
    printf("Please enter the build array size:");
    scanf("%d\n", &size);
    for (int i = 0; i < size; i++)
    {
        scanf("%d", &a[i]);
        for (int j = 0; j < i; j++)
        {
            while (a[i] == a[j])
            {
                printf("ERROR: Duplicate input data.Please try again\n");
                j = 0;
                scanf("%d\n", &a[i]);
            }
        }
    }

    printf("Array[%d]:", size);
    for (int i = 0; i < size; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

/*[2]二分法查找(升序降序都可)*/
void Interpolation_search(int *arr, int key, int sz)
{
    printf("\n");
    int left = 0;       //左边
    int right = sz - 1; //右边
    int mid;
    int min_key = -1;
    int min_key_i;
    int time = 0;
    if (arr[0] < arr[1])
    {
        /*升序*/
        while (left <= right)
        {
            time++;
             mid = left + (key - arr[left]) / (arr[right] - arr[left]) * (right - left);
            //说明key在arr[mid]和left之间
            if (arr[mid] > key)
            {
                right = mid - 1;
            }
            //说明key在arr[mid]和right之间
            else if (arr[mid] < key)
            {
                left = mid + 1;
            }
            else
            {
                printf("Interpolation_search:         array[%d]:%d     time:%d\n", mid, key, time);
                break;
            }
        }
    }
    if (left > right)
    {
        time++;
        for (int i = 0; i < sz; i++)
        {
            if (arr[i] < key)
            {
                min_key = arr[i];
                min_key_i = i;
            }
        }
        printf("Interpolation_search:         array[%d]:%d     time:%d\n", min_key_i, min_key, time);
    }

    /*降序*/
    left = 0;
    right = sz - 1; //右边
    if (arr[0] > arr[1])
    {
        while (left <= right)
        {
            time++;
             mid = left + (key - arr[left]) / (arr[right] - arr[left]) * (right - left);
            //说明key在arr[mid]和right之间
            if (arr[mid] > key)
            {
                left = mid + 1;
            }
            //说明key在arr[mid]和left之间
            else if (arr[mid] < key)
            {
                right = mid - 1;
            }
            else
            {
                printf("Interpolation_search:         array[%d]:%d     time:%d\n", mid, key, time);
                break;
            }
        }
    }
    if (left > right)
    {
        time++;
        for (int i = 0; i < sz; i++)
        {
            if (arr[i] < key && min_key == -1)
            {
                min_key = arr[i];
                min_key_i = i;
            }
        }
        printf("Interpolation_search5:         array[%d]:%d     time:%d\n", min_key_i, min_key, time);
    }
}

在这里插入图片描述


6- 三分查找

(1)三分查找(先升后降)

三分查找寻找先升后降的序列中的最大值。
这里的算法只支持先升后降的,先降后升的自己可以改一下。

#include <stdio.h>
#include <stdlib.h>

void manual_array();                             /*手动输入数组*/     
void three_divide(int *a, int size);              /*三分查找*/
int size;
int a[512];

int main(int argc, char *argv[])
{
    manual_array();

    three_divide(a, size);   

    return 0;
}
/*手动输入数组*/
void manual_array()
{
    printf("Please enter the build array size:");
    scanf("%d\n", &size);
    for (int i = 0; i < size; i++)
    {
        scanf("%d", &a[i]);
        for (int j = 0; j < i; j++)
        {
            while (a[i] == a[j])
            {
                printf("ERROR: Duplicate input data.Please try again\n");
                j = 0;
                scanf("%d\n", &a[i]);
            }
        }
    }

    printf("Array[%d]:", size);
    for (int i = 0; i < size; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

/*[4]三分查找*/
void three_divide(int *a, int size)
{
    printf("\n");
    int left = 0;
    int right = size - 1;
    int mid, mmid;
    int time = 0;
    int max;
    while (left < right - 1)
    {
        time++;
        mid = (left + right) / 2;
        mmid = (mid + right) / 2;
        if (a[mid] > a[mmid])
            right = mmid;
        else
            left = mid;
    }
    max = a[left] > a[right] ? a[left] : a[right];
    printf("[4]three_divide:     max:%d     time:%d\n", max, time);
}

在这里插入图片描述

(2)三分查找(单调递增序列)

#include <stdio.h>
#include <stdlib.h>

void manual_array();                           /*手动输入数组*/
void trichotomy(int *arr, int key, int sz);    /*三分法查找(单调序列)*/
int size;
int a[512];

int main(int argc, char *argv[])
{
    int key;
    manual_array();

    printf("Please enter the number you want to find:");
    scanf("%d", &key);
    
    trichotomy(a, key, size);

    return 0;
}
/*手动输入数组*/
void manual_array()
{
    printf("Please enter the build array size:");
    scanf("%d\n", &size);
    for (int i = 0; i < size; i++)
    {
        scanf("%d", &a[i]);
        for (int j = 0; j < i; j++)
        {
            while (a[i] == a[j])
            {
                printf("ERROR: Duplicate input data.Please try again\n");
                j = 0;
                scanf("%d\n", &a[i]);
            }
        }
    }

    printf("Array[%d]:", size);
    for (int i = 0; i < size; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

/*三分法(单调序列)*/
void trichotomy(int *arr, int key, int sz)
{
    int left = 0;       // 左边
    int right = sz - 1; // 右边
    int midd,mid;
    int time = 0;
    while (left <= right)
    {
        time++;
        mid = (right + left) / 2;
        midd = (mid + right) / 2;
        printf("left:%d mid:%d midd:%d right:%d\n",left, mid, midd, right);
        // 说明key在arr[mid]和left之间
        if (arr[mid] > key)
        {
            right = mid - 1;
        }
        // 说明key在arr[mid]和right之间
        else if (arr[mid] < key && arr[midd] > key)
        {
            left = mid + 1;
            right = midd - 1;
        }
        else if (arr[midd] < key)
        {
            left = midd +1;
        }
        else
        {
            printf("trichotomy:         array[%d]:%d     time:%d\n", midd, key, time);
            break;
        }
        
    }
}

在这里插入图片描述


7- 寻找第k小元素

(1)预排序查找第k小元素

预排序的话就是先排好序再操作呗。都排好序了,你想知道第k小元素,直接返回不久可以了。

#include <stdio.h>
#include <stdlib.h>

void random_array();   /*自动生成数组*/  
void find_min_presort(int *a, int size, int min_k);     /*预排序查找第k小元素*/         
int size;
int a[512];

int main(int argc, char *argv[])
{
    int min_k;
    random_array();

    printf("Please enter the kth number you want to find:");
    scanf("%d", &min_k);

    find_min_presort(a, size, min_k);
    return 0;
}


/*自动生成数组*/
void random_array()
{
    printf("Please enter the build array size:");
    scanf("%d", &size);
    int i, j, x;
    for (i = 0; i < size; i++)
    {
        x = rand() % 1000;
        for (j = 0; j < i; j++)
        {
            while (x == a[j])
            {
                x = rand() % 1000;
                j = 0;
            }
        }
        a[i] = x;
    }
    printf("Array[%d]:\n", size);
    for (i = 0; i < size; i++)
    {
        printf("%-3d ", a[i]);
    }
    printf("\n");
}

/*预排序查找第k小元素*/
void find_min_presort(int *a, int size, int min_k)
{
    int i, j, t;

    for (i = 0; i < size - 1; i++) //进入循环,开始遍历,遍历次数为 n-1,(最后剩下元素肯定是最小),n 为元素总个数;
    {
        for (j = 0; j < size - 1 - i; j++) //进入循环,是元素之间的循环,循环次数不断减少,因为随着 i 的增加,最大元素不断被筛选;
        {                                  //每轮比较 (n-1)-i次:两元素间比较,所以是 n-1,因为前面比较 i 轮,已经筛选了i 个最大值;
            if (a[j] > a[j + 1])           //相邻元素进行比较,满足则往下执行,不满足,则跳回for(j=....)循环
            {
                t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t; //如果满足判断语句,交换两个比较元素的值
            }
        }
    }
    printf("\nPre-sorting algorithm -------- Find the %dTH smallest element: %d\n", min_k, a[min_k - 1]);
    printf("\n");
    for (i = 0; i < size; i++) //循环打印,n 为元素总个数,注意区分循环体中循环次数的区别
    {
        printf("%-3d ", a[i]);
    }
    printf("\n");
    for (i = 0; i < size; i++)
    {
        printf("%-3d ", i + 1);
    }
    printf("\n");
}

在这里插入图片描述

(2)减可变规模查找第k小元素

#include <stdio.h>
#include <stdlib.h>

void random_array();   /*自动生成数组*/  
void swap(int a[], int i, int j);
int lomutopartition(int a[], int start, int end);
int quickselect(int a[], int start, int end, int k);      
int size;
int a[512];

int main(int argc, char *argv[])
{
    int min_k;
    random_array();

    printf("Please enter the kth number you want to find:");
    scanf("%d", &min_k);

    int find_min_k = quickselect(a, 0, size-1, min_k);
    printf("Find_min_k: %d\n",find_min_k);
    return 0;
}


/*自动生成数组*/
void random_array()
{
    printf("Please enter the build array size:");
    scanf("%d", &size);
    int i, j, x;
    for (i = 0; i < size; i++)
    {
        x = rand() % 1000;
        for (j = 0; j < i; j++)
        {
            while (x == a[j])
            {
                x = rand() % 1000;
                j = 0;
            }
        }
        a[i] = x;
    }
    printf("Array[%d]:\n", size);
    for (i = 0; i < size; i++)
    {
        printf("%-3d ", a[i]);
    }
    printf("\n");
}

/*可减可变规模查找第k小元素*/
void swap(int a[], int i, int j)
{
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
int lomutopartition(int a[], int start, int end)
{
    int p = a[start];
    int s = start;
    for (int i = start + 1; i <= end; i++)
    {
        if (a[i] < p)
        {
            s++;
            swap(a, s, i);
        }
    }
    swap(a, start, s);
    return s;
}
int quickselect(int a[], int start, int end, int k)
{
    int s = lomutopartition(a, start, end);
    if (s == start + k - 1)
    {
        return a[s];
    }
    else if (s > start + k - 1)
    {
        quickselect(a, start, s - 1, k);  
    }
    else
    {
        quickselect(a, s + 1, end, start + k - 1 - s);   
    }
}

在这里插入图片描述

(3)暴力法查找第k小元素

暴力法肯定就是暴力呗。但是这个比前面的预排序好点。因为这个暴力法一边排序一边查找,找到了就直接结束不排序了。但是上面的预排序就是先把序列全排序好了之后直接返回第k-i下标的元素。

#include <stdio.h>
#include <stdlib.h>

void random_array();   /*自动生成数组*/  
void find_min_force(int *a, int size, int min_k); /*暴力法查找第k小元素*/ 
int size;
int a[512];

int main(int argc, char *argv[])
{
    int min_k;
    random_array();

    printf("Please enter the kth number you want to find:");
    scanf("%d", &min_k);

    find_min_force(a, size, min_k);
    return 0;
}


/*自动生成数组*/
void random_array()
{
    printf("Please enter the build array size:");
    scanf("%d", &size);
    int i, j, x;
    for (i = 0; i < size; i++)
    {
        x = rand() % 1000;
        for (j = 0; j < i; j++)
        {
            while (x == a[j])
            {
                x = rand() % 1000;
                j = 0;
            }
        }
        a[i] = x;
    }
    printf("Array[%d]:\n", size);
    for (i = 0; i < size; i++)
    {
        printf("%-3d ", a[i]);
    }
    printf("\n");
}

/*暴力法查找第k小元素*/
void find_min_force(int *a, int size, int min_k)
{
    int time = 0;
    for (int i = 0; i < size; i++ && i < min_k)
    {
        for (int j = i + 1; j < size; j++)
        {

            if (a[i] > a[j])
            {
                time++;
                int temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
        }
    }
    printf("Violence finding method ------ Find the %dTH smallest element: %d     times:%d\n", min_k, a[min_k - 1], time);
}

在这里插入图片描述


8- 实验要求

这是具体实验要求,关键字的比较次数没做,只是完成了算法的设计。

  • 设计一个交互界面(例如菜单)供用户选择,如果可能,最好是一个图形化用户界面;
  • 能够人工输入或随机生成一个长度为n的整数数组,要求数组任意两个元素都互不相同;
  • 设计一个算法判断要求2中产生的整数数组是否为或未排序(输出0)、升序(输出1)、降序(输
    先升后降(输出3)、或先降后升(输出4)状态;
  • 给定某具体元素,使用顺序检索算法判断该具体元素是否出现在要求2中产生的数组中,并统计关键字比较的次数;
  • 给定某具体元素,使用多种方法(顺序查找、二分查找、三分查找、插值查找)判断该具体元素是否出现在要求2中产生的升序或降序的数组中,并统计关键字比较的次数;
    附加:若出现,返回具体元素所在的位置,否则,返回小于最接近该具体元素的位置。
  • 给定先升后降(或先降后升)数组,使用二分检索思路和三分检索思路查找该数组的最大值(或最小值),并统计关键字比较的次数。
  • 给定无序数组,使用多种方法(蛮力法、预排序、减可变规模)查找数组中第k个最小元素,并统计关键字比较的次数。
#include <stdio.h>
#include <stdlib.h>

//#define DEBUG

#ifdef DEBUG
#define test_print(format, args...) printf(format, ##args)
#else
#define test_print(format, args...) \
    do                              \
    {                               \
    } while (0)
#endif 

int g_stop = 0;
int size;
int a[512];
int quickselect_time = 0;

int Quickselect_time = 0;
int two_process_time = 0;

void menu();                                                  /*菜单*/
void switch_ch();                                             /*选择后对应执行功能*/
void manual_array();                                          /*手动输入数组*/
void random_array();                                          /*自动输入数组*/
void Judge_array(int *array, int size);                       /*判断升降(先升(降)后降(升))*/

/*前提:乱序序列*/
void Sequential_search_violence(int *a, int value, int size); /*顺序查找(非顺序)*/

/*前提:有序序列*/
void binary_search(int *arr, int key, int sz);                /*二分查找(升序降序都可)*/
void Interpolation_search(int *arr, int key, int sz);         /*插值查找*/
void trichotomy(int *arr, int key, int sz);                   /*三分查找(升序)*/

/*前提:先升后降序列*/
void three_divide(int *a, int size);                          /*三分查找最大值(小-大-小)*/
int  process(int *a, int L, int R);                           /*二分查找最大值(递归)*/

/*前提:乱序序列有序序列都可*/
void find_min_presort(int *a, int size, int min_k);           /*预排序查找第k个最小值*/
void swap(int a[], int i, int j);
int  lomutopartition(int a[], int start, int end);
int  quickselect(int a[], int start, int end, int k);         /*可减可变规模查找第k小元素*/
void find_min_force(int *a, int size, int min_k);             /*暴力法查找第k小元素*/

int main(int argc, char *argv[])
{
    menu();
    switch_ch();
    return 0;
}

/*选择后对应执行功能*/
void switch_ch()
{
    char ch;
    while (!g_stop)
    {
        ch = getchar();
        switch (ch)
        {
        case '1':
        {
            printf("===[1]-Manually enter the size of the array to be generated===\n");
            printf("--------------------------------------------------------------\n");
            manual_array();
            break;
        }
        case '2':
        {
            printf("===[2]-Generate the array size randomly===\n");
            printf("--------------------------------------------------------------\n");
            random_array();
            break;
        }

        case '3':
        {
            printf("===[3]-Judge lift===\n");
            printf("--------------------------------------------------------------\n");
            Judge_array(a, size);
            break;
        }

        case '4':
        {
            printf("===[4]-Sequential_search to find specific elements in order===\n");
            printf("--------------------------------------------------------------\n");
            int value;
            printf("Please enter the number you want to find:");
            scanf("%d", &value);
            Sequential_search_violence(a, value, size);
            break;
        }
        case '5':
        {
            printf("===[5]-Four methods find the specified element===\n");
            printf("--------------------------------------------------------------\n");
            int key;
            printf("Please enter the number you want to find:");
            scanf("%d", &key);
            Sequential_search_violence(a, key, size);
            binary_search(a, key, size);
            Interpolation_search(a, key, size);
            trichotomy(a, key, size);
            break;
        }

        case '6':
        {
            printf("===[6]-Three/Two point search to find max member===\n");
            three_divide(a, size);

            int max = process(a, 0, size - 1);
            printf("[5]two_divide:       max:%d     times:%d\n", max, two_process_time);
            break;
        }

        case '7':
        {
            printf("===[7]-Three ways to find the KTH smallest element===\n");
            int min_k;
            random_array(); /*生成无序列表*/
            printf("Enter the KTH smallest element you want to find:");
            scanf("%d", &min_k);

            int find_min_k = quickselect(a, 0, size - 1, min_k);
            printf("[7]Variable size can be reduced - Find the %dTH smallest element: %d     times:%d\n", min_k, find_min_k, Quickselect_time);
            printf("\n");

            find_min_force(a, size, min_k);
            find_min_presort(a, size, min_k);

            break;
        }
        case '8':
        {
            printf("===Welcome to come again===\n");
        }
        }
    }
}

/*菜单*/
void menu()
{
    printf("    Welcome to the implementation of the retrieval algorithm  \n");
    printf("--------------------------------------------------------------\n");
    printf("|   [1]-Manually enter the size of the array to be generated |\n");
    printf("--------------------------------------------------------------\n");
    printf("|   [2]-Generate the array size randomly                     |\n");
    printf("--------------------------------------------------------------\n");
    printf("|   [3]-Judge lift                                           |\n");
    printf("--------------------------------------------------------------\n");
    printf("|   [4]-Find specific elements in order                      |\n");
    printf("--------------------------------------------------------------\n");
    printf("|   [5]-Four methods find the specified element              |\n");
    printf("--------------------------------------------------------------\n");
    printf("|   [6]-Three/Two point search to find max member            |\n");
    printf("--------------------------------------------------------------\n");
    printf("|   [7]-Three ways to find the KTH smallest element          |\n");
    printf("--------------------------------------------------------------\n");
    printf("|   [8]-Quit                                                 |\n");
    printf("--------------------------------------------------------------\n");
}

/*自动生成数组*/
void random_array()
{
    printf("Please enter the build array size:");
    scanf("%d", &size);
    int i, j, x;
    for (i = 0; i < size; i++)
    {
        x = rand() % 1000;
        for (j = 0; j < i; j++)
        {
            while (x == a[j])
            {
                x = rand() % 1000;
                j = 0;
            }
        }
        a[i] = x;
    }
    printf("Array[%d]:\n", size);
    for (i = 0; i < size; i++)
    {
        printf("%-3d ", a[i]);
    }
    printf("\n");
}

/*手动输入数组*/
void manual_array()
{
    printf("Please enter the build array size:");
    scanf("%d\n", &size);
    for (int i = 0; i < size; i++)
    {
        scanf("%d", &a[i]);
        for (int j = 0; j < i; j++)
        {
            while (a[i] == a[j])
            {
                printf("ERROR: Duplicate input data.Please try again\n");
                j = 0;
                scanf("%d\n", &a[i]);
            }
        }
    }

    printf("Array[%d]:", size);
    for (int i = 0; i < size; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

/*判断升序降序还是先升后降还是先降后升*/
void Judge_array(int *array, int size)
{
    int a = 1, d = 1, a_d = 0, d_a = 0;
    int min_i, max_i;
    int max = array[0], min = array[0];

    /*get min and max*/
    for (int i = 0; i < size; i++)
    {
        if (array[i] > max)
        {
            max = array[i];
        }
        if (array[i] < min)
        {
            min = array[i];
        }
    }
    /*get min_i and max_i*/
    for (int i = 0; i < size; i++)
    {
        if (array[i] == max)
        {
            max_i = i;
        }
        if (array[i] == min)
        {
            min_i = i;
        }
    }
    test_print("max[%d]:%d min[%d]:%d\n", max_i, max, min_i, min);

    /*judge fall and rise*/
    for (int i = 0; i < size - 1; i++)
    {
        if (array[i + 1] > array[i])
        {
            a++;
        }

        if (array[i + 1] < array[i])
        {
            d++;
        }
    }

    /*The judgment goes up before it goes down*/
    for (int i = 0; i < max_i; i++)
    {
        if (max_i != 0 && max_i != size - 1)
        {
            if (array[i + 1] > array[i])
            {
                a_d++;
            }
        }
    }
    test_print("a_d:%d\n", a_d);
    for (int i = max_i + 1; i < size - 1; i++)
    {
        if (max_i != 0 && max_i != size - 1)
        {
            if (array[i] > array[i + 1])
            {
                a_d++;
            }
        }
    }

    /*Judgments go down before they go up*/
    for (int i = 0; i < min_i; i++)
    {
        if (min_i != 0 && min_i != size - 1)
        {
            if (array[i + 1] < array[i])
            {
                d_a++;
            }
        }
    }

    test_print("d_a:%d\n", d_a);
    for (int i = min_i + 1; i < size - 1; i++)
    {
        if (min_i != 0 && min_i != size - 1)
        {
            if (array[i] < array[i + 1])
            {
                d_a++;
            }
        }
    }

    if (a == size)
    {
        test_print("Ascending sort\n");
        printf("Ascending sort: 1\n");
    }
    else if (d == size)
    {
        test_print("Descending sort\n");
        printf("Descending sort: 2\n");
    }
    else if (a_d == size - 2)
    {
        test_print("First rise then descend\n");
        printf("First rise then descend: 3\n");
    }
    else if (d_a == size - 2)
    {
        test_print("First fall after rise\n");
        printf("First fall after rise: 4\n");
    }
    else
    {
        test_print("Random sequence\n");
        printf("Random sequence: 0\n");
    }
    test_print("a:%d d:%d a_d:%d d_a:%d\n", a, d, a_d, d_a);
}

/*[1]顺序查找*/
void Sequential_search_violence(int *a, int value, int size)
{
    printf("--------------------------------------------------------------\n");
    int rv = 0;
    int time = 0;

    for (int i = 0; i < size; i++)
    {
        time++;
        if (value == a[i])
        {
            printf("--[1]Sequential_search:     array[%d]:%d     time:%d\n", i, value, time);
            rv = 1;
        }
    }
    if (rv == 0)
    {
        printf("Not find 1\n");
    }
}

/*[9]三分法(单调序列)*/
void trichotomy(int *arr, int key, int sz)
{
    printf("\n");
    int left = 0;       // 左边
    int right = sz - 1; // 右边
    int midd,mid;
    int time = 0;
    while (left <= right)
    {
        time++;
        mid = (right + left) / 2;
        midd = (mid + right) / 2;
        //printf("left:%d mid:%d midd:%d right:%d\n",left, mid, midd, right);
        // 说明key在arr[mid]和left之间
        if (arr[mid] > key)
        {
            right = mid - 1;
        }
        // 说明key在arr[mid]和right之间
        else if (arr[mid] < key && arr[midd] > key)
        {
            left = mid + 1;
            right = midd - 1;
        }
        else if (arr[midd] < key)
        {
            left = midd +1;
        }
        else
        {
            printf("--[9]trichotomy:            array[%d]:%d     time:%d\n", midd, key, time);
            break;
        }
        
    }
}

/*[2]二分法查找(升序降序都可)*/
void binary_search(int *arr, int key, int sz)
{
    printf("\n");
    int left = 0;       //左边
    int right = sz - 1; //右边
    int mid;
    int min_key = -1;
    int min_key_i;
    int time = 0;
    if (arr[0] < arr[1])
    {
        /*升序*/
        while (left <= right)
        {
            time++;
            mid = (right + left) / 2;
            //说明key在arr[mid]和left之间
            if (arr[mid] > key)
            {
                right = mid - 1;
            }
            //说明key在arr[mid]和right之间
            else if (arr[mid] < key)
            {
                left = mid + 1;
            }
            else
            {
                printf("--[2]Binary_search:         array[%d]:%d     time:%d\n", mid, key, time);
                break;
            }
        }
    }
    if (left > right)
    {
        time++;
        for (int i = 0; i < sz; i++)
        {
            if (arr[i] < key)
            {
                min_key = arr[i];
                min_key_i = i;
            }
        }
        printf("--[2]Binary_search:         array[%d]:%d     time:%d\n", min_key_i, min_key, time);
    }

    /*降序*/
    left = 0;
    right = sz - 1; //右边
    if (arr[0] > arr[1])
    {
        while (left <= right)
        {
            time++;
            mid = (right + left) / 2;
            //说明key在arr[mid]和right之间
            if (arr[mid] > key)
            {
                left = mid + 1;
            }
            //说明key在arr[mid]和left之间
            else if (arr[mid] < key)
            {
                right = mid - 1;
            }
            else
            {
                printf("--[2]Binary_search:         array[%d]:%d     time:%d\n", mid, key, time);
                break;
            }
        }
    }
    if (left > right)
    {
        time++;
        for (int i = 0; i < sz; i++)
        {
            if (arr[i] < key && min_key == -1)
            {
                min_key = arr[i];
                min_key_i = i;
            }
        }
        printf("--[2]Binary_search:         array[%d]:%d     time:%d\n", min_key_i, min_key, time);
    }
    test_print("mid: %d\n", mid);
    test_print("left: %d right: %d\n", left, right);
}

/*[3]插值查找*/
void Interpolation_search(int *arr, int key, int sz)
{
    /*升序*/
    printf("\n");
    int time = 0;
    int left = 0;       //左边
    int right = sz - 1; //右边
    int mid;
    int min_key = -1;
    int min_key_i;
    if (arr[0] < arr[1])
    {
        while (left <= right)
        {
            time++;
            mid = left + (key - arr[left]) / (arr[right] - arr[left]) * (right - left);
            //说明key在arr[mid]和left之间
            if (arr[mid] > key)
            {
                right = mid - 1;
            }
            //说明key在arr[mid]和right之间
            else if (arr[mid] < key)
            {
                left = mid + 1;
            }
            else
            {
                printf("--[3]Interpolation_search:  array[%d]:%d     time:%d\n", mid, key, time);
                break;
            }
        }

        if (left > right)
        {
            time++;
            for (int i = 0; i < sz; i++)
            {
                if (arr[i] < key)
                {
                    min_key = arr[i];
                    min_key_i = i;
                }
            }
            printf("--[3]Interpolation_search:  array[%d]:%d     time%d:\n", min_key_i, min_key, time);
        }
    }

    /*降序*/
    left = 0;
    right = sz - 1; //右边
    if (arr[0] > arr[1])
    {
        while (left <= right)
        {
            time++;
            mid = left + (key - arr[left]) / (arr[right] - arr[left]) * (right - left);
            //说明key在arr[mid]和right之间
            if (arr[mid] > key)
            {
                left = mid + 1;
            }
            //说明key在arr[mid]和left之间
            else if (arr[mid] < key)
            {
                right = mid - 1;
            }
            else
            {
                printf("--[3]Interpolation_search:  array[%d]:%d     time:%d\n", mid, key, time);
                break;
            }
        }
        if (left > right)
        {
            time++;
            for (int i = 0; i < sz; i++)
            {
                if (arr[i] < key && min_key == -1)
                {
                    min_key = arr[i];
                    min_key_i = i;
                }
            }
            printf("--[3]Interpolation_search:  array[%d]:%d     time:%d\n", min_key_i, min_key, time);
        }
    }
    test_print("mid: %d\n", mid);
    test_print("left: %d right: %d\n", left, right);
}

/*[4]三分查找*/
void three_divide(int *a, int size)
{
    printf("\n");
    int left = 0;
    int right = size - 1;
    int mid, mmid;
    int time = 0;
    int max;
    while (left < right - 1)
    {
        time++;
        mid = (left + right) / 2;
        mmid = (mid + right) / 2;
        if (a[mid] > a[mmid])
            right = mmid;
        else
            left = mid;
    }
    max = a[left] > a[right] ? a[left] : a[right];
    printf("[4]three_divide:     max:%d     time:%d\n", max, time);
}

/*[5]二分查找(先升后降)*/
int process(int *a, int L, int R)

{
    // L是该段数据的左边界
    // R是该段数据的右边界
    if (L == R)
    {
        two_process_time ++;
        return *(a + L);
    }
    int mid = L + ((R - L) / 2); //计算中点
    int Leftmax = process(a, L, mid);
    int Rightmax = process(a, mid + 1, R);
    two_process_time ++;
    return (Leftmax > Rightmax) ? Leftmax : Rightmax;
}

/*[6]预排序查找第k小元素*/
void find_min_presort(int *a, int size, int min_k)
{
    int i, j, t;

    for (i = 0; i < size - 1; i++) //进入循环,开始遍历,遍历次数为 n-1,(最后剩下元素肯定是最小),n 为元素总个数;
    {
        for (j = 0; j < size - 1 - i; j++) //进入循环,是元素之间的循环,循环次数不断减少,因为随着 i 的增加,最大元素不断被筛选;
        {                                  //每轮比较 (n-1)-i次:两元素间比较,所以是 n-1,因为前面比较 i 轮,已经筛选了i 个最大值;
            if (a[j] > a[j + 1])           //相邻元素进行比较,满足则往下执行,不满足,则跳回for(j=....)循环
            {
                t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t; //如果满足判断语句,交换两个比较元素的值
            }
        }
    }
    printf("\n[6]Pre-sorting algorithm -------- Find the %dTH smallest element: %d\n", min_k, a[min_k - 1]);
    printf("\n");
    for (i = 0; i < size; i++) //循环打印,n 为元素总个数,注意区分循环体中循环次数的区别
    {
        printf("%-3d ", a[i]);
    }
    printf("\n");
    for (i = 0; i < size; i++)
    {
        printf("%-3d ", i + 1);
    }
    printf("\n");
}

/*[7]减可变规模查找第k小元素*/
void swap(int a[], int i, int j)
{
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
int lomutopartition(int a[], int start, int end)
{
    int p = a[start];
    int s = start;
    for (int i = start + 1; i <= end; i++)
    {
        if (a[i] < p)
        {
            Quickselect_time ++;
            s++;
            swap(a, s, i);
        }
    }
    swap(a, start, s);
    return s;
}
int quickselect(int a[], int start, int end, int k)
{
    int s = lomutopartition(a, start, end);
    if (s == start + k - 1)
    {
        Quickselect_time ++;
        return a[s];
    }
    else if (s > start + k - 1)
    {
        quickselect(a, start, s - 1, k);  
    }
    else
    {
        quickselect(a, s + 1, end, start + k - 1 - s);   
    }
}

/*[8]暴力法查找第k小元素*/
void find_min_force(int *a, int size, int min_k)
{
    int time = 0;
    for (int i = 0; i < size; i++ && i < min_k)
    {
        for (int j = i + 1; j < size; j++)
        {

            if (a[i] > a[j])
            {
                time++;
                int temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
        }
    }
    printf("[8]Violence finding method ------ Find the %dTH smallest element: %d     times:%d\n", min_k, a[min_k - 1], time);
}

在这里插入图片描述
这是菜单,具体功能自己去测试吧。


  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是用C语言递归算法实现二分查找的代码: ```c #include <stdio.h> int binarySearch(int arr[], int left, int right, int target) { if (right >= left) { int mid = left + (right - left) / 2; if (arr[mid] == target) { return mid; } if (arr[mid] > target) { return binarySearch(arr, left, mid - 1, target); } return binarySearch(arr, mid + 1, right, target); } return -1; } int main() { int arr[] = {2, 4, 6, 8, 10, 12, 14, 16}; int n = sizeof(arr) / sizeof(arr[0]); int target = 10; int result = binarySearch(arr, 0, n - 1, target); if (result == -1) { printf("Element not found"); } else { printf("Element found at index %d", result); } return 0; } ``` 上述代码中,`binarySearch`函数实现二分查找。它接收一个整数数组、左边界、右边界和目标元素作为参数,并返回目标元素在数组中的索引。如果目标元素不在数组中,则返回-1。 在函数中,我们首先计算中间元素的索引,然后将目标元素与中间元素进行比较。如果中间元素等于目标元素,则返回中间元素的索引。如果中间元素大于目标元素,则递归调用`binarySearch`函数,在左子数组中查找目标元素。如果中间元素小于目标元素,则递归调用`binarySearch`函数,在右子数组中查找目标元素。 在`main`函数中,我们定义了一个整数数组`arr`、目标元素`target`,并调用`binarySearch`函数在数组中查找目标元素。最后,根据返回判断目标元素是否在数组中,并输出结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值