哈工大(威海)算法实验一:分治算法实验大作业
哈工大(威海)算法实验一:分治算法实验大作业
题目
某一高等院校有汽车学院、材料学院、计算机学院、软件学院;每个学院的一年级第一学期都开英语、高数、线代课程。每个学院每学期的成绩已经分别登录在同一个Excel文件的不同Sheet(表)中,没有排序,人数分别为,N1,N2,N3,N4
(2020年朱东杰老师的算法课,实验一大作业,仅供参考)
(具体的python jupyter notebook文件和数据Excel文件已经打包上传资源到CSDN了,链接:哈工大(威海) 算法设计与分析 朱东杰老师 实验一(分治算法实验))
任务
1.按单科成绩排序算法
2.输出在全校英语成绩前k名的学生名单(学院、学号、姓名、英语成绩)
3.输出在全校英语、高数、线代成绩都是前k名的学生名单(学院、学号、姓名、英语、高数、线代成绩)
题解
任务一:使用归并排序。首先将各个表中的数据读入到一个数组中(笔者使用python的openpyxl库来实现Excel的读取,并使用list来存储每个学生的信息),之后实现divide函数和merge函数。
使用递归法实现归并排序:
1.将序列每相邻两个数字进行归并操作,形成floor(n/2)个序列,排序后每个序列包含两个元素
2.将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素
3.重复步骤2,直到所有元素排序完毕
merge函数 (将子序列合并)
def merge(arr, left, right, flag):mid = int((right - left)/2 + left)temp = []i = leftj = mid + 1while i < mid + 1 and j < right + 1: # 合并两个有序的子序列if arr[i][flag] < arr[j][flag]:temp.append(arr[j])j = j + 1else:temp.append(arr[i])i = i + 1while i < mid + 1:temp.append(arr[i])i = i + 1while j < right + 1:temp.append(arr[j])j = j + 1index = 0for k in range(left, right + 1): # 使用合并后的有序序列更新原序列arr[k] = temp[index]index = index + 1
divide函数 (将原序列拆分,并进行递归,调用merge函数)
def divide(arr, left, right, flag): # flag = 2英语; flag = 3高数; flag = 4代数if right - left < 1:return 0else:mid = int((right - left) / 2 + left)divide(arr, left, mid, flag)divide(arr, mid + 1, right, flag)merge(arr, left, right, flag)
任务二:使用分治法求最大值的算法。
传统的求序列中最大值和最小值的算法是很直接对序列进行扫描,需要2n-2次比较操作,使用分治的思想,可以优化到比较3n/2-2次比较操作
如上图,不断划分序列,直到每一小段只有两个元素,一个为此小序列的最大值,一个为此小序列的最大值,之后再将两个有序的小序列合并,不断重复此过程,只需要比较合并的两个序列的最大值和最小值,并不断更新这两个值即可。具体伪代码可参考下图:
findMax函数
def findMax(arr, left, right, flag): #分治法求最大值max_temp1 = [10001, '无名氏', 0, 0, 0, '未知学院'] #初始化max_temp2 = [10002, '无名氏', 0, 0, 0, '未知学院'] #初始化if left == right: return arr[left]elif left == right - 1: #获得最大值,并返回if arr[left][flag] > arr[right][flag]:return arr[left]else:return arr[right]else:mid = (left + right) // 2max_temp1 = findMax(arr, left, mid, flag) #继续分段max_temp2 = findMax(arr, mid + 1, right, flag)if max_temp1[flag] > max_temp2[flag]: #比较左右两端哪个的最大值更大return max_temp1else:return max_temp2
在有了这个可以求得最大值的算法后,想要求得序列的前k大值,只需要每次使用这个算法,求得当前序列的最大值,之后从序列中删除这个最大值即可。
findKMax函数
def findKMax(arr, ans, k, flag): #求前K大个值for i in range(0, k):tempAns = findMax(arr, 0, len(arr) - 1, flag)ans.append(tempAns)arr.remove(tempAns)
任务三:要获得各项成绩都是前k名的学生名单,那么可以用一个set存储某项科目成绩前k名的学生姓名,之后在获得下一项科目成绩前k名的学生姓名名单后,新建一个临时的set,如果此名单中的姓名出现在了前一个set中,将名字添加到这个临时的set中去,之后使用临时的set的值更新原来的set的值,重复此过程即可获得各项成绩都是前k名的学生姓名集合。然后遍历一遍整个成绩表,寻找集合中的学生姓名对应的成绩信息即可。
getAllKMax函数
def getAllKMax(arr, k): #各项成绩都是前k名nameSet = set()for i in range(2, 5):tempSet = set() # 临时的集合ans = []arr_temp = arr[:]findKMax(arr_temp, ans, k, i)for j in range(0, len(ans)):if i == 2:nameSet.add(ans[j][1])else:if ans[j][1] in nameSet:tempSet.add(ans[j][1])if i != 2:nameSet = tempSetreturn nameSet
代码
from openpyxl import load_workbook
import copyworkbook = load_workbook('2020算法实验1:分治算法实验.xlsx')sheet_car = workbook['汽车学院']
sheet_material = workbook['材料学院']
sheet_computer = workbook['计算机学院']
sheet_software = workbook['软件学院']data_car_temp = sheet_car['C5':'G11']
data_material_temp = sheet_material['C5':'G13']
data_computer_temp = sheet_computer['C5':'G11']
data_software_temp = sheet_software['C5':'G11']def dataProcess(data_temp, data, flag):for i in range(0, len(data_temp)):temp = []for j in range(0, 5):temp.append(data_temp[i][j].value)if flag == 1:temp.append("汽车学院")if flag == 2:temp.append("材料学院")if flag == 3:temp.append("计算机学院")if flag == 4:temp.append("软件学院")data.append(temp)data_all = []
dataProcess(data_car_temp, data_all, 1)
dataProcess(data_material_temp, data_all, 2)
dataProcess(data_computer_temp, data_all, 3)
dataProcess(data_software_temp, data_all, 4)def merge(arr, left, right, flag):mid = int((right - left)/2 + left)temp = []i = leftj = mid + 1while i < mid + 1 and j < right + 1:if arr[i][flag] < arr[j][flag]:temp.append(arr[j])j = j + 1else:temp.append(arr[i])i = i + 1while i < mid + 1:temp.append(arr[i])i = i + 1while j < right + 1:temp.append(arr[j])j = j + 1index = 0for k in range(left, right + 1):arr[k] = temp[index]index = index + 1def divide(arr, left, right, flag): # flag = 2英语; flag = 3高数; flag = 4代数if right - left < 1:return 0else:mid = int((right - left) / 2 + left)divide(arr, left, mid, flag)divide(arr, mid + 1, right, flag)merge(arr, left, right, flag)# 打印降序排序后的单科成绩名单
divide(data_all, 0, len(data_all) - 1, 2)
print(data_all)def findMax(arr, left, right, flag): #分治法求最大值max_temp1 = [10001, '无名氏', 0, 0, 0, '未知学院']max_temp2 = [10002, '无名氏', 0, 0, 0, '未知学院']if left == right:return arr[left]elif left == right - 1:if arr[left][flag] > arr[right][flag]:return arr[left]else:return arr[right]else:mid = (left + right) // 2max_temp1 = findMax(arr, left, mid, flag)max_temp2 = findMax(arr, mid + 1, right, flag)if max_temp1[flag] > max_temp2[flag]:return max_temp1else:return max_temp2def findKMax(arr, ans, k, flag): #求前K大个值for i in range(0, k):tempAns = findMax(arr, 0, len(arr) - 1, flag)ans.append(tempAns)arr.remove(tempAns)# 打印单项成绩是前k名的学生名单
data_temp = data_all[:]
ans = []
findKMax(data_temp, ans, 5, 2)
for i in range(len(ans)):print(ans[i][0],ans[i][1],ans[i][2],ans[i][5])def getAllKMax(arr, k): #各项成绩都是前k名nameSet = set()for i in range(2, 5):tempSet = set()ans = []arr_temp = arr[:]findKMax(arr_temp, ans, k, i)for j in range(0, len(ans)):if i == 2:nameSet.add(ans[j][1])else:if ans[j][1] in nameSet:tempSet.add(ans[j][1])if i != 2:nameSet = tempSetreturn nameSet# 打印各项成绩都是前k名的学生名单
data_temp = data_all[:]
nameSet = getAllKMax(data_temp, 5)
for i in range(0, len(data_all)):if data_all[i][1] in nameSet:print(data_all[i])
哈工大(威海)算法实验一:分治算法实验大作业相关推荐
- 【数据结构与算法】【算法思想】分治算法
贪心算法 回溯算法 分治算法 动态规划 MapReduce本质就是分治算法,是Google大数据处理的三驾马车之一,另外两个是GFS和Bigtable.它在倒排索引,PageRank计算,网页分析等搜 ...
- 天津理工大学研究生学位课《算法设计与分析》期末大作业
2022- 2023学年度第一学期 研究生学位课< 算法设计与分析 > 期末大作业 2022级电子信息天理研究生 一.简答题 1.若,写出用Θ.Ω和О描述f(n) 的渐进表达.(7分) 答 ...
- 快速排序 c++_算法浅谈——分治算法与归并、快速排序(附代码和动图演示)
本文始发于个人公众号:TechFlow 在之前的文章当中,我们通过海盗分金币问题详细讲解了递归方法. 我们可以认为在递归的过程当中,我们通过函数自己调用自己,将大问题转化成了小问题,因此简化了编码以及 ...
- 计算机基础算法棋盘覆盖,分治算法求解棋盘覆盖问题互动教学过程.doc
分治算法求解棋盘覆盖问题互动教学过程 分治算法求解棋盘覆盖问题互动教学过程 摘要:针对算法设计与分析课程难度较大.对学生编程能力要求较高的现状,通过对棋盘覆盖问题的分治算法求解过程进行互动教学设计,引 ...
- 算法导论系列:分治算法
说起分治法,大家一定也都听过秦始皇采用郡县制将国家分为三十六郡的故事,我们常说"山高皇帝远",意思就是山高路远,皇帝都管不了,实际上无论皇帝多远,山有多高,整个国家都属于朝廷统治, ...
- 排序中减治法算法伪代码_算法浅谈——分治算法与归并、快速排序(附代码和动图演示)...
在之前的文章当中,我们通过海盗分金币问题详细讲解了递归方法. 我们可以认为在递归的过程当中,我们通过函数自己调用自己,将大问题转化成了小问题,因此简化了编码以及建模.今天这篇文章呢,就正式和大家聊一聊 ...
- c语言分治算法之归并排序,分治算法之归并排序
分治算法: 将一个规模为N的问题分解为K个规模较小的子问题,这些子问题互相独立且与原问题性质相同.求出子问题的解后进行合并,就可得到原问题的解. 一般步骤: 1.分解,将要解决的问题划分成若干规模较小 ...
- 【算法概论】分治算法:k路归并
首先了解两个概念,胜者树和败者树: 胜者树和败者树都是二叉排序树,是树形选择排序的一种变形.每个叶子节点相当于一位选手,每个中间结点相当于一场比赛,每一层相当于一轮比赛.胜者树的中间结点记录的是胜者的 ...
- 五大常用算法之一:分治算法
分治算法 一.基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题-- ...
- 程序员都会的五大算法之一(分治算法),恶补恶补恶补!!!
前言 点击查看算法介绍 五大算法 分治算法 动态规划 贪心算法 回溯算法 分支限界算法 WX搜素"Java长征记"对这些算法也有详细介绍. 分治算法 一.算法概述 简单来说,分治算 ...
最新文章
- FLASHCS3多文件上传源代码(类似uccenter社区)
- nltk自然语言处理
- samba客户端的总结与归纳
- ThinikPhp 将数据库模型的增、删、改操作写入日志
- object c 快速构建对象
- 前端学习(2877):原生js模块化+绘制弹幕与动画video联动
- 透明大页相关内核参数_透明大内存页Hugepage支持
- CAShapeLayer的使用[1]
- 第二章--电商设计表-商品模块--mysql电商项目设计
- DEBUGGING AND OPTIMIZING MEMORY
- python可视化直方图的代码
- 棋牌搭建,APP新手教程
- Qt中其他类调用窗口中的ui控件
- PLC可编程控制器、单片机开发应用及变频调速综合实训装置
- 如何设计一个超级牛逼的 Feed 流系统
- ssms管理linux数据库,SQL Server 2017 Developer的下载、安装、配置及SSMS的下载安装配置(图文教程详解)...
- js动态向页面添加元素
- labview文件上传服务器,基于labview的局域网TCP传输文件夹问题的解决
- 身份证过期了,银行卡上的身份证信息是不是都要去银行更新?
- Dev-C++游戏创作之金山打字通(附带音乐)