数据结构课程实践系列
题目1:学生成绩档案管理系统(实验准备)
题目2:隐式图的搜索问题(A*算法解决八数码)
题目3:文本文件单词的检索与计数(实验准备)
文章目录
声明
实验要求
- 学生信息录入,信息包括学号、姓名、专业、四门课成绩、总分、名次;
- 系统可对学生信息浏览、增加、删除和修改;
- 按学生成绩确定名次及信息输出,双向冒泡排序、希尔排序、快速排序、堆排序
- 要求可对学生信息查询,根据学号或姓名进行查找;
- 信息修改仅可修改四门课成绩;
- 文件存取学生信息。
编程语言以及开发环境的选择
编程语言:java
开发环境:IDE使用的是idea,jdk版本为1.8
所需知识
一些简单排序算法,以及DAO
所需知识导出
DAO运用
DAO
(Database Access Object) 数据访问对象,将数据对象常用的访问方法(增删改查)封装在指定的对象中,该对象就称为DAO对象,DAO对象是数据层构建的基础,由业务层对象进行调用,DAO中定义的数据访问方法和业务无关。
DAO设计模式主要分为三层:
- 显示层:主要使用
JSP/Servlet
进行页面效果的显示 - 业务层:(Business Object,数据对象)会将多个原子性的DAO操作进行组合,组合成一个完整的业务逻辑。
- 数据层:(DAO,Data Access Object,数据库访问对象)提供多个原子性的DAO操作,例如:增、删、改、查,都是原子性操作。
其实也就是利用一个Dao对象,然后这个对象里面实现了相应的增删改查,不让用户去直接接触到数据库。感觉和windows中线性虚拟地址的运用有着相同的味道
简单排序算法
双向冒泡排序
传统冒泡排序运作如下:(从后往前)
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
双向冒泡排序算法的运作如下:
- 传统冒泡气泡排序的双向进行,先让气泡排序由左向右进行,再来让气泡排序由右往左进行,如此完成一次排序的动作
- 使用left与right两个旗标来记录左右两端已排序的元素位置。
public List<Student> doubleBubbleSort(List<Student> studentList){
List<Student> list=studentList;
Student student=null;
int left=0,right=studentList.size()-1;
while(left<right)
{
for(int i=left+1;i<=right;i++){
if(list.get(left).getSum()<list.get(i).getSum()){
student=list.get(i);
list.set(i,list.get(left));
list.set(left,student);
}
}
left++;
for(int i=right-1;i>=left;i--){
if(list.get(right).getSum()>list.get(i).getSum()){
student=list.get(i);
list.set(i,list.get(right));
list.set(right,student);
}
}
right--;
}
return list;
}
快速排序
快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
快速排序算法的运作如下:
- 从数列中挑出一个元素,称为“基准”(pivot),
- 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作
- 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
public List<Student> quickSort(List<Student> studentList){
List<Student> list=studentList;
quickSort1(list,0,list.size()-1);
return list;
}
public void quickSort1(List<Student> studentList,int left,int right){
if(left<right){
int i=left,j=right;
Student student=studentList.get(left);
double x=student.getSum();
while(i<j){
while((i<j)&&(studentList.get(j).getSum()<x)){
j--;
}
if(i<j){
studentList.set(i,studentList.get(j));
i++;
}
while((i<j)&&(studentList.get(i).getSum()>x)){
i++;
}
if(i<j){
studentList.set(j,studentList.get(i));
j--;
}
}
studentList.set(i,student);
quickSort1(studentList,left,i-1);
quickSort1(studentList,i+1,right);
}
}
希尔排序
希尔排序是非稳定排序算法,把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
public List<Student> shellSort(List<Student> studentList){
List<Student> list=studentList;
Student student=null;
int j;
for (int gap = list.size() / 2; gap > 0; gap /= 2) {
for (int i = gap; i < list.size(); i++) {
student=list.get(i);
double tmp=student.getSum();
for (j = i; j >= gap && tmp>list.get(j-gap).getSum(); j -= gap) {
list.set(j,list.get(j-gap));
}
list.set(j,student);
}
}
return list;
}
堆排序
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
public List<Student> heapSort(List<Student> studentList){
List<Student> list=studentList;
int len = list.size();
buildMaxHeap(list, len);
for (int i = len - 1; i > 0; i--) {
swap(list, 0, i);
len--;
heapify(list, 0, len);
}
return list;
}
private void buildMaxHeap(List<Student> studentList, int len) {
for (int i = (int) Math.floor(len / 2); i >= 0; i--) {
heapify(studentList, i, len);
}
}
private void heapify(List<Student> studentList, int i, int len) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int largest = i;
if (left < len && studentList.get(left).getSum() < studentList.get(largest).getSum()) {
largest = left;
}
if (right < len && studentList.get(right).getSum() < studentList.get(largest).getSum()) {
largest = right;
}
if (largest != i) {
swap(studentList, i, largest);
heapify(studentList, largest, len);
}
}
private void swap(List<Student> studentList, int i, int j) {
Student student=studentList.get(i);
studentList.set(i,studentList.get(j));
studentList.set(j,student);
}