文章目录
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);
}
这是菜单,具体功能自己去测试吧。