哈工大(威海)算法实验一:分治算法实验大作业

题目

某一高等院校有汽车学院、材料学院、计算机学院、软件学院;每个学院的一年级第一学期都开英语、高数、线代课程。每个学院每学期的成绩已经分别登录在同一个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])

哈工大(威海)算法实验一:分治算法实验大作业相关推荐

  1. 【数据结构与算法】【算法思想】分治算法

    贪心算法 回溯算法 分治算法 动态规划 MapReduce本质就是分治算法,是Google大数据处理的三驾马车之一,另外两个是GFS和Bigtable.它在倒排索引,PageRank计算,网页分析等搜 ...

  2. 天津理工大学研究生学位课《算法设计与分析》期末大作业

    2022- 2023学年度第一学期 研究生学位课< 算法设计与分析 > 期末大作业 2022级电子信息天理研究生 一.简答题 1.若,写出用Θ.Ω和О描述f(n) 的渐进表达.(7分) 答 ...

  3. 快速排序 c++_算法浅谈——分治算法与归并、快速排序(附代码和动图演示)

    本文始发于个人公众号:TechFlow 在之前的文章当中,我们通过海盗分金币问题详细讲解了递归方法. 我们可以认为在递归的过程当中,我们通过函数自己调用自己,将大问题转化成了小问题,因此简化了编码以及 ...

  4. 计算机基础算法棋盘覆盖,分治算法求解棋盘覆盖问题互动教学过程.doc

    分治算法求解棋盘覆盖问题互动教学过程 分治算法求解棋盘覆盖问题互动教学过程 摘要:针对算法设计与分析课程难度较大.对学生编程能力要求较高的现状,通过对棋盘覆盖问题的分治算法求解过程进行互动教学设计,引 ...

  5. 算法导论系列:分治算法

    说起分治法,大家一定也都听过秦始皇采用郡县制将国家分为三十六郡的故事,我们常说"山高皇帝远",意思就是山高路远,皇帝都管不了,实际上无论皇帝多远,山有多高,整个国家都属于朝廷统治, ...

  6. 排序中减治法算法伪代码_算法浅谈——分治算法与归并、快速排序(附代码和动图演示)...

    在之前的文章当中,我们通过海盗分金币问题详细讲解了递归方法. 我们可以认为在递归的过程当中,我们通过函数自己调用自己,将大问题转化成了小问题,因此简化了编码以及建模.今天这篇文章呢,就正式和大家聊一聊 ...

  7. c语言分治算法之归并排序,分治算法之归并排序

    分治算法: 将一个规模为N的问题分解为K个规模较小的子问题,这些子问题互相独立且与原问题性质相同.求出子问题的解后进行合并,就可得到原问题的解. 一般步骤: 1.分解,将要解决的问题划分成若干规模较小 ...

  8. 【算法概论】分治算法:k路归并

    首先了解两个概念,胜者树和败者树: 胜者树和败者树都是二叉排序树,是树形选择排序的一种变形.每个叶子节点相当于一位选手,每个中间结点相当于一场比赛,每一层相当于一轮比赛.胜者树的中间结点记录的是胜者的 ...

  9. 五大常用算法之一:分治算法

    分治算法 一.基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题-- ...

  10. 程序员都会的五大算法之一(分治算法),恶补恶补恶补!!!

    前言 点击查看算法介绍 五大算法 分治算法 动态规划 贪心算法 回溯算法 分支限界算法 WX搜素"Java长征记"对这些算法也有详细介绍. 分治算法 一.算法概述 简单来说,分治算 ...

最新文章

  1. FLASHCS3多文件上传源代码(类似uccenter社区)
  2. nltk自然语言处理
  3. samba客户端的总结与归纳
  4. ThinikPhp 将数据库模型的增、删、改操作写入日志
  5. object c 快速构建对象
  6. 前端学习(2877):原生js模块化+绘制弹幕与动画video联动
  7. 透明大页相关内核参数_透明大内存页Hugepage支持
  8. CAShapeLayer的使用[1]
  9. 第二章--电商设计表-商品模块--mysql电商项目设计
  10. DEBUGGING AND OPTIMIZING MEMORY
  11. python可视化直方图的代码
  12. 棋牌搭建,APP新手教程
  13. Qt中其他类调用窗口中的ui控件
  14. PLC可编程控制器、单片机开发应用及变频调速综合实训装置
  15. 如何设计一个超级牛逼的 Feed 流系统
  16. ssms管理linux数据库,SQL Server 2017 Developer的下载、安装、配置及SSMS的下载安装配置(图文教程详解)...
  17. js动态向页面添加元素
  18. labview文件上传服务器,基于labview的局域网TCP传输文件夹问题的解决
  19. 身份证过期了,银行卡上的身份证信息是不是都要去银行更新?
  20. Dev-C++游戏创作之金山打字通(附带音乐)

热门文章

  1. css表格样式、颜色渐变、计数器
  2. 奶牛跨栏--最短路径--佛洛依德算法
  3. VMware 各版本下载教程
  4. 观后感《改变地球的一代人》
  5. POJ 大数篇(POJ+百炼)
  6. Java中 String类的详解(非常全面细致)
  7. 相亲婚恋交友网站建设制作,第五篇
  8. 唉,这几天的问题好头痛
  9. python+selenium实现的谷歌爬虫(超详细)
  10. 关于m个n-1维几何体最大分割n维空间问题的解法