实验4:查找与排序综合应用

实验4:查找与排序综合应用

  1. 采用二分查找的方法实现查找
    (1)定义顺序表的存储结构;
    (2)实现顺序表上二分查找;
  2. 采用二叉排序树实现查找
    (1)定义二叉链表的存储结构;
    (2)实现二叉排序树的建立、查找、插入和删除结点操作;
  3. 冒泡排序
    (1)定义顺序表的存储结构;
    (2)在顺序表上实现冒泡排序;
    (3)将普通的冒泡排序进行多次改进以提高排序速度,并用大量数据测试其速度的提高。
  4. 快速排序
    (1)定义顺序表的存储结构;
    (2)在顺序表上实现快速排序;
    (3)用大量的数据测试最好、最坏和平均情况下的排序速度。
  5. 堆排序
    (1)定义顺序表的存储结构;
    (2)在顺序表上实现堆排序;
    (3)用大量的数据测试最好、最坏和平均情况下的排序速度。
  6. 比较各种排序方法的优缺点和适用场合

1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#define bug(BUG) std::cout << "bug::" << BUG << std::endl;
#define bug2(BUG1, BUG2) std::cout << "bug::" << BUG1 << ' ' << BUG2 << std::endl;
constexpr int MaxSize = 1000, mod = MaxSize;struct List
{int data[MaxSize];int len;
};void BinarySearch(List &list, const int tar)
{int l = -1, r = list.len - 1;while (r - l - 1){int mid = l + r >> 1;if (list.data[mid] >= tar)r = mid;elsel = mid;}if (list.data[r] == tar)printf("%d的下标为%d\n", tar, r);elseprintf("未找到%d\n", tar);
}
int main()
{int n; // 元素个数scanf("%d", &n);List list;list.len = n;//  读入有序表for (int i = 0; i < n; i++)scanf("%d", &list.data[i]);puts("有序表:>_<");for (int i = 0; i < list.len; i++)printf("%d ", list.data[i]);puts("");BinarySearch(list, 1);BinarySearch(list, 6);BinarySearch(list, 12);BinarySearch(list, 20);BinarySearch(list, 50);BinarySearch(list, 128);BinarySearch(list, 256);BinarySearch(list, 512);BinarySearch(list, 1024);BinarySearch(list, 4096);
}//  测试数据
/*
20
1 2 3 4 5 6 10 12 18 29
49 40 60 64 128 256 512 1024 2048 4096
*///  测试结果
/*
有序表:>_<
1 2 3 4 5 6 10 12 18 29 49 40 60 64 128 256 512 1024 2048 4096
1的下标为0
6的下标为5
12的下标为7
未找到20
未找到50
128的下标为14
256的下标为15
512的下标为16
1024的下标为17
4096的下标为19*/

2

#include <stdio.h>
#include <stdlib.h>// 二叉链表节点结构
typedef struct Node
{int value;          // 节点存储的值struct Node *left;  // 指向左子节点的指针struct Node *right; // 指向右子节点的指针
} Node;Node *createNode(int value)
{Node *newNode = (Node *)malloc(sizeof(Node));newNode->value = value;newNode->left = NULL;newNode->right = NULL;return newNode;
}Node *insert(Node *root, int value)
{if (root == NULL)return createNode(value);if (value < root->value) // 小于当前节点值,插入左子树root->left = insert(root->left, value);else // 大于或等于当前节点值,插入右子树root->right = insert(root->right, value);return root;
}Node *search(Node *root, int value)
{if (root == NULL || root->value == value)return root; // 找到节点或树为空if (value < root->value) // 在左子树中查找return search(root->left, value);else // 在右子树中查找return search(root->right, value);
}Node *findMin(Node *root) // 找到最小节点
{while (root->left != NULL)root = root->left;return root;
}Node *deleteNode(Node *root, int value)
{if (root == NULL)return root;if (value < root->value) // 在左子树中删除root->left = deleteNode(root->left, value);else if (value > root->value) // 在右子树中删除root->right = deleteNode(root->right, value);else{if (root->left == NULL) // 只有右子树{Node *temp = root->right;free(root);return temp;}else if (root->right == NULL) // 只有左子树{Node *temp = root->left;free(root);return temp;}// 节点有两个子树,找到右子树的最小值Node *temp = findMin(root->right);root->value = temp->value;                          // 用右子树的最小值替代当前节点root->right = deleteNode(root->right, temp->value); // 删除右子树中的最小值}return root;
}int main()
{Node *root = NULL;root = insert(root, 50);root = insert(root, 30);root = insert(root, 20);root = insert(root, 40);root = insert(root, 70);root = insert(root, 60);root = insert(root, 80);root = deleteNode(root, 20);Node *found = search(root, 30);if (found)printf("找到节点: %d\n", found->value);elseprintf("未找到节点 30\n");return 0;
}

3

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#define bug(BUG) std::cout << "bug::" << BUG << std::endl;
#define bug2(BUG1, BUG2) std::cout << "bug::" << BUG1 << ' ' << BUG2 << std::endl;
constexpr int MaxSize = 30000, mod = MaxSize;struct List
{int data[MaxSize];int len;
};void swap(int &a, int &b, int &cnt)
{a = a ^ b, b = a ^ b, a = a ^ b;cnt += 3;
}
void BubbleSort(List list)
{int cnt = 0;for (int i = 0; i < list.len - 1; i++)for (int j = list.len - 1; j > 0; j--){cnt++;if (list.data[j - 1] > list.data[j])swap(list.data[j - 1], list.data[j], cnt);}printf("BubbleSort的运算次数:%d\n运算结果:_<  ", cnt);// for (int i = 0; i < list.len; i++)//     printf("%d ", list.data[i]);puts("");
}//  改进的冒泡排序
void BubbleSortTurbo(List list)
{int cnt = 0;for (int i = 0; i < list.len - 1; i++){bool is_sorted = 1;for (int j = list.len - 1; j > i; j--){cnt++;if (list.data[j - 1] > list.data[j])swap(list.data[j - 1], list.data[j], cnt), is_sorted = 0;}if (is_sorted)break;}printf("改进后BubbleSort的运算次数:%d\n运算结果:_<", cnt);// for (int i = 0; i < list.len; i++)//     printf("%d ", list.data[i]);puts("");
}int main()
{int n;scanf("%d", &n);List list;list.len = n;for (int i = 0; i < n; i++)scanf("%d", &list.data[i]);BubbleSort(list);// BubbleSortTurbo(list);
}// 数据与结果// 10
// 4 5 6 2 3 4 5 6 7 0
// BubbleSort的运算次数:99
// 运算结果:_<  0 2 3 4 4 5 5 6 6 7
// 改进后BubbleSort的运算次数:57
// 运算结果:_<  0 2 3 4 4 5 5 6 6 7// 1000个随机数
// BubbleSort的运算次数:1746855
// 改进后BubbleSort的运算次数:1247273// 5000个随机数
// BubbleSort的运算次数:43820554
// 改进后BubbleSort的运算次数:31324048// 10000个随机数
// BubbleSort的运算次数:175330872
// 改进后BubbleSort的运算次数:125328293// 30000个随机数
// BubbleSort的运算次数:1576654462  平均用时:1823ms
// 改进后BubbleSort的运算次数:1126694511  平均用时:1460ms

4

#include <stdio.h>
#include <stdlib.h>
#include <time.h>typedef struct
{int *data; // 指向数据的指针int size;  // 当前元素的个数
} SequentialList;// 创建顺序表
SequentialList *createList(int capacity)
{SequentialList *list = (SequentialList *)malloc(sizeof(SequentialList));list->data = (int *)malloc(capacity * sizeof(int));list->size = 0;return list;
}void freeList(SequentialList *list)
{if (list){free(list->data);free(list);}
}void swap(int *a, int *b)
{int temp = *a;*a = *b;*b = temp;
}// 划分函数
int partition(int *arr, int low, int high)
{int pivot = arr[high]; // 选择最后一个元素作为支点int i = low - 1;       // 分区指针for (int j = low; j < high; j++){if (arr[j] < pivot){ // 当前元素小于支点i++;swap(&arr[i], &arr[j]); // 交换}}swap(&arr[i + 1], &arr[high]); // 将支点放到正确位置return i + 1;                  // 返回支点索引
}// 快速排序的递归实现
void quickSort(int *arr, int low, int high)
{if (low < high){int pi = partition(arr, low, high); // 划分quickSort(arr, low, pi - 1);        // 递归排序左半部分quickSort(arr, pi + 1, high);       // 递归排序右半部分}
}// 快速排序的入口
void sort(SequentialList *list)
{if (list->size > 0){quickSort(list->data, 0, list->size - 1);}
}// 生成随机数据
void generateRandomData(SequentialList *list, int size)
{list->size = size;for (int i = 0; i < size; i++){list->data[i] = rand() % 100000;}
}// 测试排序速度
void testSort(int dataSize)
{SequentialList *list = createList(dataSize);generateRandomData(list, dataSize);clock_t start = clock();sort(list);clock_t end = clock();double timeSpent = (double)(end - start) / CLOCKS_PER_SEC;printf("排序 %d 个元素耗时: %.6f 秒\n", dataSize, timeSpent);freeList(list);
}int main()
{srand((unsigned)time(NULL));// 测试不同规模的数据testSort(100000);   // 测试100000个元素testSort(1000000);  // 测试1000000个元素testSort(10000000); // 测试10000000个元素return 0;
}// 测试结果// 排序 100000 个元素耗时: 0.006000 秒
// 排序 1000000 个元素耗时: 0.093000 秒
// 排序 10000000 个元素耗时: 1.619000 秒

5

#include <stdio.h>
#include <stdlib.h>
#include <time.h>typedef struct
{int *data; // 指向数据的指针int size;  // 当前元素数量
} SequentialList;// 创建顺序表
SequentialList *createList(int capacity)
{SequentialList *list = (SequentialList *)malloc(sizeof(SequentialList));list->data = (int *)malloc(capacity * sizeof(int));list->size = 0;return list;
}void freeList(SequentialList *list)
{if (list){free(list->data);free(list);}
}// 交换两个元素
void swap(int &a, int &b)
{a = a ^ b, b = a ^ b, a = a ^ b;
}// 构建最大堆
void heapify(int *arr, int n, int i)
{int largest = i;       // 初始化最大的元素为根int left = 2 * i + 1;  // 左子节点int right = 2 * i + 2; // 右子节点// 如果左子节点比根节点大if (left < n && arr[left] > arr[largest])largest = left;// 如果右子节点比当前最大值还大if (right < n && arr[right] > arr[largest])largest = right;// 如果最大的不是根if (largest != i){swap(arr[i], arr[largest]); // 交换heapify(arr, n, largest);   // 递归堆化}
}// 堆排序的主要函数
void heapSort(int *arr, int n)
{// 构建最大堆for (int i = n / 2 - 1; i >= 0; i--)heapify(arr, n, i);// 提取元素从堆中,进行排序for (int i = n - 1; i > 0; i--){swap(arr[0], arr[i]); // 将当前最大值交换到数组末尾heapify(arr, i, 0);   // 重新调整堆}
}// 堆排序的接口
void sort(SequentialList *list)
{if (list->size > 0){heapSort(list->data, list->size);}
}// 生成随机数据
void generateRandomData(SequentialList *list, int size)
{list->size = size;for (int i = 0; i < size; i++){list->data[i] = rand() % 10000000;}
}// 测试排序速度
void testSort(int dataSize)
{SequentialList *list = createList(dataSize);generateRandomData(list, dataSize);clock_t start = clock();sort(list);clock_t end = clock();double timeSpent = (double)(end - start) / CLOCKS_PER_SEC;printf("排序 %d 个元素耗时: %.6f 秒\n", dataSize, timeSpent);freeList(list);
}int main()
{srand((unsigned)time(NULL));// 测试不同规模的数据testSort(100000);  // 测试100000个元素testSort(1000000); // 测试1000000个元素testSort(5000000); // 测试5000000个元素return 0;
}// 测试结果// 排序 100000 个元素耗时: 0.014000 秒
// 排序 1000000 个元素耗时: 0.174000 秒
// 排序 5000000 个元素耗时: 1.203000 秒

6

// 1. 冒泡排序 (Bubble Sort)
// 优点:// 实现简单、容易理解。
// 对于小规模数据集或部分有序的数据集合效果较好;如果数据基本有序,冒泡排序仍能保持 O(n) 的时间复杂度。
// 缺点:// 平均和最坏情况时间复杂度是 O(n²),对于大规模数据集效率较低。
// 不适合大规模数据集。
// 适用场合:// 学习和教学目的,展示排序算法的基本思想。
// 小规模或几乎有序的数据集。
// 2. 选择排序 (Selection Sort)
// 优点:// 实现简单,操作简单。
// 不需要额外的内存,空间复杂度为 O(1)。
// 缺点:// 平均和最坏情况时间复杂度是 O(n²),对于大规模数据集效率不高。
// 效率比冒泡排序和插入排序略差,特别是在数据量增大时。
// 适用场合:// 数据量较小时可用,或内存资源有限的情况。
// 3. 插入排序 (Insertion Sort)
// 优点:// 当数据集比较小且几乎有序时,效率较高,时间复杂度可以达到 O(n)。
// 实现简单,且是稳定的排序算法。
// 不需要额外的空间,空间复杂度为 O(1)。
// 缺点:// 平均和最坏情况时间复杂度为 O(n²),不适合大规模无序数据。
// 适用场合:// 小规模数据、部分有序的数据集,或合并多个已经排序的序列。
// 4. 希尔排序 (Shell Sort)
// 优点:// 相比于简单的 O(n²) 的排序算法更高效,特别是对于中等规模的数据集。
// 适用于大规模数据排序,有较好的性能。
// 缺点:// 实现比简单排序复杂。
// 最坏时间复杂度是不定的,视增量序列而定,常见的增量序列使其最坏情况时间复杂度为 O(n²)。
// 适用场合:// 中等规模的数据集,数据并不完全有序的情况。
// 5. 归并排序 (Merge Sort)
// 优点:// 时间复杂度为 O(n log n),在最坏情况下仍然保持稳定。
// 稳定的排序算法,适合链表等数据结构。
// 当数据量非常大时,可以使用外部排序(如文件排序)。
// 缺点:// 需要 O(n) 的额外空间,内存开销较大。
// 实现相对复杂。
// 适用场合:// 数据量大、需要稳定性,或是数据在磁盘等外部存储中的情况。
// 6. 快速排序 (Quick Sort)
// 优点:// 平均时间复杂度为 O(n log n),在大多数情况下表现优秀。
// 适合大数据集,且空间复杂度较低(O(log n))。
// 缺点:// 最坏情况下(如已经排序的列表)时间复杂度为 O(n²),但通过随机化或优化可以减少这种情况的发生。
// 不稳定的排序算法。
// 适用场合:// 大规模数据排序,一般情况下使用最广泛的排序算法。
// 7. 堆排序 (Heap Sort)
// 优点:// 时间复杂度为 O(n log n),并且在最坏情况下保证此性能。
// 不需要额外的内存,空间复杂度为 O(1)。
// 缺点:// 不是稳定的排序算法。
// 相比于快速排序和归并排序,性能可能稍差。
// 适用场合:// 数据量较大时,是一种不错的选择,尤其是在对内存使用有严格限制的场合。
// 8. 计数排序 (Counting Sort)
// 优点:// 时间复杂度为 O(n + k),其中 k 是数据范围,效率非常高。
// 是稳定的排序算法。
// 缺点:// 只能用于整数或可整形的数据,适用范围有限。
// 需要 O(k) 的额外空间。
// 适用场合:// 数量较少且范围已知的整数集合,适合对特定范围内的整数进行排序。
// 9. 基数排序 (Radix Sort)
// 优点:// 对于数字或字母,效率很高,时间复杂度为 O(nk),k 是数字的位数。
// 稳定的排序算法。
// 缺点:// 对于小范围的整数排序效率不佳,空间复杂度也较高。
// 适用场合:// 适合对整数字或字符串等多位数据进行排序。
// 总结
// 选择排序算法时,需考虑数据规模、数据特点、时间和空间复杂度需求以及稳定性要求等因素。对于小规模数据,简单排序算法可能更合适;而对于大数据集,快速排序和归并排序通常是更好的选择。选择合适的排序算法可以更有效地提高程序性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/65404.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Maven + MyBatis

文章目录 Maven 配置mybatis-config.xml 核心配置文件模板mybatis 映射 mapper可以 package不可以解决 Maven目录结构 Maven 配置 核心配置文件 <?xml version"1.0" encoding"UTF-8" ?> <!-- .dtd约束 --> <!DOCTYPE configurationPUBLIC…

【最新】西陆房产系统源码+uniapp全开源+环境教程

一.介绍 西陆房产管理系统&#xff0c;支持小程序、H5、APP&#xff1b;包含房客、房东(高级授权)、经纪人(高级授权)三种身份。核心功能有&#xff1a;新盘销售、房屋租赁、地图找房、房源代理(高级授权)、在线签约(高级授权)、电子合同(高级授权)、客户CRM跟进(高级授权)、经…

Elasticsearch检索之三:官方推荐方案search_after检索实现(golang)

Elasticsearch8.17.0在mac上的安装 Kibana8.17.0在mac上的安装 Elasticsearch检索方案之一&#xff1a;使用fromsize实现分页 快速掌握Elasticsearch检索之二&#xff1a;滚动查询(scrool)获取全量数据(golang) 1、search_after检索 在前面的文章介绍了fromsize的普通分页…

小程序基础 —— 10 如何调试小程序代码

如何调试小程序代码 在进行项目开发的时候&#xff0c;不可避免需要进行调试&#xff0c;那么如何调试小程序呢&#xff1f; 打开微信开发者工具后&#xff0c;有一个模拟器&#xff0c;通过模拟器能够实时预览自己写的页面&#xff0c;如下&#xff1a; 在上部工具栏中有一个…

VLM和VLAM(VLA)相关介绍和发展历程

目录 一、个人感想二、相关介绍2.1 视觉语言模型 (VLM) 的发展历程2.2 视觉语言动作模型 (VLA) 的发展历程2.3 一些关键的研究工作&#xff1a;一些架构图 三、发展历程3.1 视觉语言模型 (VLM) 的发展时间线3.2 视觉语言动作模型 (VLA) 的发展时间线 四、参考资料 一、个人感想…

算法题(18):删除有序数组中的重复项2

审题&#xff1a; 需要原地删除数据让数组中一个数据只能出现最多2次&#xff0c;并返回修改后的数组的数据个数 &#xff08;不会有空数组情况&#xff09; 思路&#xff1a; 双指针&#xff1a;我们用left指向下一个需要插入数据的位置&#xff0c;right去遍历数组 left数据的…

IPv6 基础协议-NDP

IPv6 基础协议报文 何为基础协议&#xff1f;像v4中的icmp、arp、hdcp之类的 在v6中只需要NDP协议&#xff0c;他是通过ICMPv6报文完成的&#xff0c;她能够实现邻居发现、无状态地址检测、重复地址检测、PMTU等功能 RS&#xff08;133&#xff09;RA&#xff08;134&#x…

MySQL外键类型与应用场景总结:优缺点一目了然

前言&#xff1a; MySQL的外键简介&#xff1a;在 MySQL 中&#xff0c;外键 (Foreign Key) 用于建立和强制表之间的关联&#xff0c;确保数据的一致性和完整性。外键的作用主要是限制和维护引用完整性 (Referential Integrity)。 主要体现在引用操作发生变化时的处理方式&…

分布式事务入门 一

分布式事务入门 一 您好&#xff0c;我是今夜写代码,今天学习下分布式事务相关理论&#xff0c;以及常见的解决方案&#xff0c;为后续掌握Seata分布式事务框奠定基础。 为什么需要分布式事务? 分布式事务主要由于存储资源的分布性&#xff0c;通常涉及多个数据库。 分布式…

Goland:专为Go语言设计的高效IDE

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;Goland是JetBrains公司开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为Go语言设计&#xff0c;提供了高效的代码编辑、强大的调试工具和丰富的项目管理功能。其智能代码补全、强大的调试与测试支…

uniapp 前端解决精度丢失的问题 (后端返回分布式id)

原因&#xff1a; 后端使用分布式id, id为19位数&#xff0c;导致精度丢失 &#xff0c;前端解决方法 这个是通过浏览器请求回来的数据&#xff0c;这个时候id 数据已经丢失了&#xff0c;在数据库查询不到&#xff0c;在调获详情接口的时候会有问题 实际的&#xff1a; 解决…

读书笔记-《乡下人的悲歌》

前段时间看了一些 J.D. Vance 的采访视频&#xff0c;几乎都是记者带着刁难的问题先手进攻&#xff0c;而 Vance 面带微笑&#xff0c;提及对方的名字&#xff0c;条理清晰地从对方的攻击中切回主题形成后手反制&#xff0c;实在让人看得过瘾。 更不可思议的是&#xff0c;Van…

Datawhale-AI冬令营二期

目录 一、番茄时钟&#xff08;1&#xff09;输入Prompt&#xff08;2&#xff09;创建 HTML 文件解析1&#xff1a;HTML结构解析2&#xff1a;计时器内容解析3&#xff1a;按钮区域解析4&#xff1a;脚本引用 &#xff08;3&#xff09;使用JavaScript实现时钟功能解析1&#…

【Sentinel】流控效果与热点参数限流

目录 1.流控效果 1.1.warm up 2.2.排队等待 1.3.总结 2.热点参数限流 2.1.全局参数限流 2.2.热点参数限流 2.3.案例 1.流控效果 在流控的高级选项中&#xff0c;还有一个流控效果选项&#xff1a; 流控效果是指请求达到流控阈值时应该采取的措施&#xff0c;包括三种&…

我的Qt作品(20)使用Qt+OpenCV写一个旋转/抠图/mask生成工具

使用QtOpenCV写一个旋转/抠图/mask生成工具 1、旋转功能 void FormRotate::rotateImage(const cv::Mat &src, cv::Mat &dst, double degree) //旋转 {if (fabs(degree) < 0.001){dst src;return;}//center旋转的中心点坐标//degree旋转的角度,不是弧度,>0逆时针…

win11中win加方向键失效的原因

1、可能是你把win键锁了&#xff1a; 解决办法&#xff1a;先按Fn键&#xff0c;再按win键 2、可能是可能是 贴靠窗口设置 中将贴靠窗口关闭了&#xff0c;只需要将其打开就好了

MetaRename for Mac,适用于 Mac 的文件批量重命名工具

在处理大量文件时&#xff0c;为每个文件手动重命名既耗时又容易出错。对于摄影师、设计师、开发人员等需要频繁处理和整理文件的专业人士来说&#xff0c;找到一款能够简化这一过程的工具是至关重要的。MetaRename for Mac 就是这样一款旨在提高工作效率的应用程序&#xff0c…

JavaScript甘特图 dhtmlx-gantt

背景 需求是在后台中&#xff0c;需要用甘特图去展示管理任务相关视图&#xff0c;并且不用依赖vue&#xff0c;兼容JavaScript原生开发。最终使用dhtmlx-gantt&#xff0c;一个半开源的库&#xff0c;基础功能免费&#xff0c;更多功能付费。 甘特图需求如图&#xff1a; 调…

VSCode下载安装指南

VSCode下载 通过网盘分享的文件&#xff1a;VSCodeUserSetup-x64-1.96.2.exe 链接: https://pan.baidu.com/s/1l7fdxeALnyeuUe1a5l0aqQ?pwdb8y3 提取码: b8y3 –来自百度网盘超级会员v6的分享 VSCode安装 1、下载好之后双击下图 2、我同意&#xff0c;下一步 3、可以点浏…

【黑马头条】day20—xxl-job

目录 1 今日内容 1.1 需求分析 1.2 实现思路 1.3 定时计算 1.4 定时任务框架-xxljob 1.5 学习目录 2.分布式任务调度 2.1 什么是分布式任务调度 2.2 xxl-Job简介 2.3 XXL-Job-环境搭建 2.4 配置部署调度中心-docker安装 2.5 xxl-job入门案例编写 2.6 任务详解-执行…