南京师范大学计电院数据结构课设——排序算法

news2025/2/27 17:33:05

1 排序算法

1.1 题目要求

编程实现希尔、快速、堆排序、归并排序算法。要求首先随机产生10000个数据存入磁盘文件,然后读入数据文件,分别采用不同的排序方法进行排序并将结果存入文件中。

1.2 算法思想描述

1.2.1 随机数生成

当需要生成一系列随机数时,常常需要使用随机函数。然而,传统的rand()函数所生成的数据并不能被视为真正的随机数,因其仅限于某个特定范围内的值,并且在多次运行同一rand()函数时,所产生的随机数序列是完全一致的,缺乏真正的随机性。为此,我们需要借助srand()函数来设置rand()函数生成随机数时的种子值,通过不同的种子值,我们可以获得不同的随机数序列。

为了实现更接近真正随机数的序列生成,一种常见的做法是利用srand((int)time(NULL))的方式,即利用系统时钟来产生随机数种子。该方法将当前时间转换为一个整数,并将其作为srand()函数的参数,以初始化随机数生成器的种子值。由于时间的变化是无法预测的,因此每次程序运行时都会获得一个不同的种子值,从而产生不同的随机数序列。

图1.1 随机生成数示例代码

1.2.2 希尔排序

希尔排序(Shell Sort)是一种基于插入排序的排序算法,它通过将待排序的元素按照一定的间隔分组,对每组进行插入排序,随着间隔逐渐减小,最终使得整个序列达到有序状态。

下面是希尔排序的基本思想和实现步骤:

  1. 选择一个间隔序列(称为增量序列),通常初始间隔为数组长度的一半,然后逐步缩小间隔直到为1。
  2. 对于每个间隔,将数组分成多个子序列,子序列的元素之间相隔间隔个位置。
  3. 对每个子序列进行插入排序,即将子序列中的元素按照插入排序的方式进行排序。
  4. 重复步骤2和步骤3,直到间隔为1时,进行最后一次插入排序。

图1.2 希尔排序示例代码

1.2.3 快速排序

快速排序(Quick Sort)是一种高效的排序算法,它采用分治法(Divide and Conquer)策略来排序一个数组。快速排序的基本思想是选择一个基准元素(pivot),将数组分割成两个子数组,其中一个子数组的元素都比基准元素小,另一个子数组的元素都比基准元素大,然后对这两个子数组分别进行递归排序,最终将整个数组排序完成。

图1.3 快速排序示例代码

1.2.4 堆排序

堆排序(Heap Sort)是一种利用堆数据结构进行排序的算法。堆是一种完全二叉树,具有以下性质:对于每个节点i,其父节点的值小于等于节点i的值(最大堆),或者父节点的值大于等于节点i的值(最小堆)。在堆排序中,我们使用最大堆来进行排序。

下面是堆排序的基本思想和实现步骤:

  1. 把无序数组构建成二叉堆。
  2. 循环删除堆顶元素,移到集合尾部,调节堆产生新的堆顶。
  3. 当删除一个最大堆的堆顶(并不是完全删除,而是替换到最后面),经过自我调节,第二大的元素就会被交换上来,成为最大堆的新堆顶。由于这个特性,我们每一次删除旧堆顶,调整后的新堆顶都是大小仅次于旧堆顶的节点。那么我们只要反复删除堆顶,反复调节二叉堆,所得到的集合就成为了一个有序集合。

图1.4 堆排序示例代码

1.2.5 归并排序

归并排序(Merge Sort)是一种基于分治法(Divide and Conquer)的排序算法,它将待排序的数组逐步分割成较小的子数组,然后将这些子数组逐个合并,最终得到一个有序的数组。合并2个数组的称为2路归并,合并3个数组的称为3路归并,多路归并。归并排序是稳定的。

图1.5 归并排序示例代码

1.3 程序设计

1.3.1 程序设计思路

图1.6 程序设计思路图

1.3.2 生成input.txt文件

先创建一个文件并打开,然后生成随机数存储到该文件中作为后续的输入文件。

图1.7 生成input.txt文件代码

1.3.3 生成排序结果文件

首先完成文件的存入函数,再分别调用不同的排序算法完成排序再存入对应的文件中。

图1.8将数据存入文件代码

图1.9 排序并存入文件代码

1.3.4完整代码(C++)

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

// 生成随机数并保存到文件
void generateRandomNumbers(const std::string& filename, int count) {
    std::ofstream file(filename);
    if (!file.is_open()) {
        std::cout << "无法打开文件:" << filename << std::endl;
        return;
    }
    else
    {
        std::cout << "生成成功"<<std::endl;
    }
    srand(time(NULL));
    for (int i = 0; i < count; ++i) {
        int num = rand() % 100000;  // 生成0到99999之间的随机数
        file << num << std::endl;
    }
    file.close();
}

// 从文件中读取数据
std::vector<int> readNumbersFromFile(const std::string& filename) {
    std::vector<int> numbers;
    std::ifstream file(filename);
    if (!file.is_open()) {
        std::cout << "无法打开文件:" << filename << std::endl;
        return numbers;
    }

    int num;
    while (file >> num) {
        numbers.push_back(num);
    }

    file.close();
    return numbers;
}

// 将数据存入文件
void writeNumbersToFile(const std::string& filename, const std::vector<int>& numbers) {
    std::ofstream file(filename);
    if (!file.is_open()) {
        std::cout << "无法打开文件:" << filename << std::endl;
        return;
    }
    else
    {
        std::cout << "存入成功"<<std::endl;
    }
    for (int num : numbers) {
        file << num << std::endl;
    }

    file.close();
}

// 希尔排序
void shellSort(std::vector<int>& numbers) {
    int n = numbers.size();
    for (int gap = n / 2; gap > 0; gap /= 2) {
        for (int i = gap; i < n; ++i) {
            int temp = numbers[i];
            int j = i;
            while (j >= gap && numbers[j - gap] > temp) {
                numbers[j] = numbers[j - gap];
                j -= gap;
            }
            numbers[j] = temp;
        }
    }
}

// 快速排序
void quickSort(std::vector<int>& numbers, int low, int high) {
    if (low < high) {
        int pivot = numbers[high];
        int i = low - 1;
        for (int j = low; j <= high - 1; ++j) {
            if (numbers[j] < pivot) {
                ++i;
                std::swap(numbers[i], numbers[j]);
            }
        }
        std::swap(numbers[i + 1], numbers[high]);
        int partitionIndex = i + 1;
        quickSort(numbers, low, partitionIndex - 1);
        quickSort(numbers, partitionIndex + 1, high);
    }
}

// 堆排序
void heapify(std::vector<int>& numbers, int n, int i) {
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;

    if (left < n && numbers[left] > numbers[largest])
        largest = left;

    if (right < n && numbers[right] > numbers[largest])
        largest = right;

    if (largest != i) {
        std::swap(numbers[i], numbers[largest]);
        heapify(numbers, n, largest);
    }
}

void heapSort(std::vector<int>& numbers) {
    int n = numbers.size();
    for (int i = n / 2 - 1; i >= 0; --i)
        heapify(numbers, n, i);

    for (int i = n - 1; i >= 0; --i) {
        std::swap(numbers[0], numbers[i]);
        heapify(numbers, i, 0);
    }
}

// 归并排序
void merge(std::vector<int>& numbers, int left, int middle, int right) {
    int n1 = middle - left + 1;
    int n2 = right - middle;

    std::vector<int> leftArr(n1);
    std::vector<int> rightArr(n2);

    for (int i = 0; i < n1; ++i)
        leftArr[i] = numbers[left + i];
    for (int j = 0; j < n2; ++j)
        rightArr[j] = numbers[middle + 1 + j];

    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (leftArr[i] <= rightArr[j]) {
            numbers[k] = leftArr[i];
            ++i;
        }
        else {
            numbers[k] = rightArr[j];
            ++j;
        }
        ++k;
    }

    while (i < n1) {
        numbers[k] = leftArr[i];
        ++i;
        ++k;
    }

    while (j < n2) {
        numbers[k] = rightArr[j];
        ++j;
        ++k;
    }
}

void mergeSort(std::vector<int>& numbers, int left, int right) {
    if (left < right) {
        int middle = left + (right - left) / 2;
        mergeSort(numbers, left, middle);
        mergeSort(numbers, middle + 1, right);
        merge(numbers, left, middle, right);
    }
}

int main() {
    // 生成随机数并保存到文件
    generateRandomNumbers("input.txt", 10000);

    // 从文件中读取数据
    std::vector<int> numbers = readNumbersFromFile("input.txt");

    // 复制数据用于各种排序算法
    std::vector<int> numbersShell = numbers;
    std::vector<int> numbersQuick = numbers;
    std::vector<int> numbersHeap = numbers;
    std::vector<int> numbersMerge = numbers;

    // 希尔排序
    shellSort(numbersShell);
    // 将结果存入文件
    writeNumbersToFile("shell_sorted.txt", numbersShell);

    // 快速排序
    quickSort(numbersQuick, 0, numbersQuick.size() - 1);
    // 将结果存入文件
    writeNumbersToFile("quick_sorted.txt", numbersQuick);

    // 堆排序
    heapSort(numbersHeap);
    // 将结果存入文件
    writeNumbersToFile("heap_sorted.txt", numbersHeap);

    // 归并排序
    mergeSort(numbersMerge, 0, numbersMerge.size() - 1);
    // 将结果存入文件
    writeNumbersToFile("merge_sorted.txt", numbersMerge);

    return 0;
}

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

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

相关文章

jupyter notebook闪退解决,安美解决

jupyter notebook闪退 解决方法 打开这个目录 删除含有“~”开头的文件 解决

nebula容器方式安装:docker 安装nebula到windows

感谢阅读 基础环境安装安装docker下载nebula 安装数据库命令行安装查询network nebula-docker-compose_nebula-net并初始化查询安装初始使用root&#xff08;God用户类似LINUX的root&#xff09; 关闭服务 安装UI 基础环境安装 安装docker 点我下载docker 下载nebula 数据…

Redis高可用三主三从集群部署

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容使用宝塔面板搭建集群规划配置验证 使用docker搭建使用脚本搭建&#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博…

数字经济的蓬勃发展:Web3的崛起

在当今数字化时代&#xff0c;数字经济已经成为全球经济的新引擎&#xff0c;而Web3技术的兴起则为其注入了新的活力和可能性。本文将深入探讨数字经济的蓬勃发展以及Web3技术对其的影响和推动作用。 1. 数字经济的定义和发展 数字经济是指以数字化技术为基础&#xff0c;利用…

系统攻防-WindowsLinux远程探针本地自检任意代码执行权限提升入口点

知识点&#xff1a; 1、远程漏扫-Nessus&Nexpose&Goby 2、本地漏扫(提权)-Wesng&Tiquan&Suggester 3、利用场景-远程利用&本地利用&利用条件 一、演示案例-操作系统-远程漏扫-Nessus&Nexpose&Goby Nessus Nessus号称是世界上最流行的漏洞扫描…

【Leetcode每日一题】二分查找 - 在排序数组中查找元素的第一个和最后一个位置(难度⭐⭐)(18)

1. 题目解析 Leetcode链接&#xff1a;34. 在排序数组中查找元素的第一个和最后一个位置 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 核心在于找到给定目标值所在的数组下标区间&#xff0c;设计一个O(logn)的算法。 2. 算法原…

[Docker 教学] 常用的Docker 命令

Docker是一种流行的容器化技术。使用Docker可以将数据科学应用程序连同代码和所需的依赖关系打包成一个名为镜像的便携式工件。因此&#xff0c;Docker可以简化开发环境的复制&#xff0c;并使本地开发变得轻松。 以下是一些必备的Docker命令列表&#xff0c;这些命令将在你下一…

K8S部署Java项目(Gitlab CI/CD自动化部署终极版)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

编曲学习:和声小调 终止式 离调和弦 转调应用

和声小调 音阶 大调音程关系排列:全 全 半 全 全 全 半 小调音程关系排列:全 半 全 全 半 全 全 C大调音阶: 1 2 3 4 5 6 7 1 C小调音阶: 1 2 b3 4 5 b6 b7 1 C大调基本音级构成的和弦: Cmaj7 Dmin7 Emin7 Fmaj7 G7 Amin7 Bm7-5 C小调基本音级构成的和弦: Cmin7 D…

Mycat核心教程--ZooKeeper集群搭建【三】

Mycat核心教程--ZooKeeper集群搭建 八、 ZooKeeper集群搭建8.1.ZooKeeper简介8.2.数据复制的好处8.3.Zookeeper设计目的8.4.zookeeper集群包括3种角色8.4.1.Leader角色8.4.2.Follower 角色8.4.3.Observer 角色 8.5.zookeeper集群工作流程8.6.zookeeper集群节点数量为奇数&#…

stm32——hal库学习笔记(DMA实验)

一、DMA介绍&#xff08;了解&#xff09; 二、DMA结构框图介绍&#xff08;熟悉&#xff09; 三、DMA相关寄存器介绍&#xff08;熟悉&#xff09; 四、DMA相关HAL库驱动介绍&#xff08;掌握&#xff09; 五、DMA配置步骤&#xff08;掌握&#xff09; 六、编程实战&#xff…

进程间通信学习笔记(有名管道和无名管道)

进程间通信方式&#xff1a; 无名管道(pipe)有名管道(fifo)信号(signal)共享内存(mmap)套接字(socket) 无名管道&#xff1a; 在内核里面开辟一片内存&#xff0c;进程1和进程2都可以通过这片内存进行通信 无名管道特点&#xff1a; 只能用于具有亲缘关系的进程之间的通信&am…

5Why分析法不会用?别担心,精益企业管理咨询公司助你解锁新技能

近年来&#xff0c;为了保持竞争力&#xff0c;许多企业开始转向精益管理&#xff0c;而5Why分析法则是实现这一目标的关键工具之一。然而&#xff0c;对于许多初学者来说&#xff0c;5Why分析法可能显得陌生和复杂。今天&#xff0c;天行健精益企业管理咨询公司就来分享如何运…

浅谈 FD 、PCB 以及 进程内存布局

文章目录 名词解释概念介绍进程内存布局 名词解释 FD&#xff1a;file description&#xff0c;文件描述符&#xff0c;是一个指针变量。 PCB&#xff1a;进程控制块。 概念介绍 我们知道&#xff0c;linux 里面的文件都有基本信息&#xff0c;例如&#xff1a;文件路径、文…

Redis 管道详解

Redis 管道 关键词&#xff1a;Pipeline Pipeline 简介 Redis 是一种基于 C/S 模型以及请求/响应协议的 TCP 服务。通常情况下&#xff0c;一个 Redis 命令的请求、响应遵循以下步骤&#xff1a; 客户端向服务端发送一个查询请求&#xff0c;并监听 Socket 返回&#xff08…

SAR ADC学习笔记(2)

SAR ADC工作原理 基本算法&#xff1a;二进制搜索 / 折半查找 SAR ADC基本结构&#xff1a;采样保持电路、电容DAC、比较器、SAR逻辑

Docker Volume

"Ice in my vein" Docker Volume(存储卷) 什么是存储卷? 存储卷就是: “将宿主机的本地文件系统中存在的某个目录&#xff0c;与容器内部的文件系统上的某一目录建立绑定关系”。 存储卷与容器本身的联合文件系统&#xff1f; 在宿主机上的这个与容器形成绑定关系…

BLEU: a Method for Automatic Evaluation of Machine Translation

文章目录 BLEU: a Method for Automatic Evaluation of Machine Translation背景和意义技术原理考虑 n n n - gram中 n 1 n1 n1 的情况考虑 n n n - gram中 n > 1 n\gt 1 n>1 的情况考虑在文本中的评估初步实验评估和结论统一不同 n n n 值下的评估数值考虑句子长度…

在培训机构中备考PMP为什么题库这么重要?

参加过培训和考试&#xff0c;对题库的了解也就越来越深了&#xff0c;刚开始接触PMP的时候以为学习的时候会像其他考试一样有官方题库进行参考&#xff0c;但是了解后才发现一切都没有我想的那么简单&#xff0c;也是在威班PMP培训的时候才知道题库是多重要。 PMI有官方题库吗…

等保测评与商用密码共铸工控安全“双评合规”新篇章

最近听说了一个段子&#xff1a;“网络安全就像美女的内衣&#xff0c;等保和密评就是最贴身的内衣两件套&#xff0c;上下身一件都不能少。否则你的魔鬼身材&#xff08;核心数据&#xff09;就有可能被色狼&#xff08;黑客&#xff09;一览无余&#xff08;数据泄漏&#xf…