目录
1 问题描述 2
2 需求分析 2
2.1 基本需求 2
2.2 功能需求 2
3 概要设计 3
3.1抽象数据类型 3
3.2 总体设计 3
3.3 用户界面及功能模块设计 4
4 详细设计及系统实现 6
4.1 核心算法设计 6
4.3 各功能模块实现 9
5 系统调试分析 10
6 项目运行展示 10
7 课程设计总结 12
参考文献 13
附录:源码以及其它相关材料 13

2.需求分析
项目在Vs环境下用c++完成,添加Qt tools插件,动画部分用Qt实现。
2.1基本要求
1)实现各种内部排序。
2)以动画的形式展示每一趟数组元素的变化。
3)待排序的元素的关键字为整数。其中的数据要用随机数产生(如10000个),至少用5组不同的数据做比较,再使用各种算法对其进行排序,记录其排序时间,再汇总比较;
4)构建可视化界面,对操作过程进行动画展示;
5)实现伪代码与动画同步进行,演示程序要交互进行,要求算法执行与存储结构的同步动态变化;
2.2功能要求
1)界面设计(参考界面如图1所示)
a.界面要求可以进行交互,要求实现图形界面而不是简单的控制台应用,界面要求美观、布局合理,符合用户使用习惯。
b.对于每种排序方式,可以在界面进行选择。
c.可视化系统(如窗体、web网页、App、微信小程序等)
2)要求至少要实现以下算法:
冒泡排序、快速排序、简单插入排序、希尔排序、简单选择排序与堆排序。
3)随机生成数据\用户输入数据
对于操作中使用的数据,可以由电脑随机生成或者是用户自行在所设计界面中输入数据可以生成指定数据。
4)算法比较
每次测试完毕显示各种比较指标值的列表(包括执行时间、关键字移动次数、交换次数等),用饼图或条形图进行表示,以便比较各种排序的优劣。
5)动画演示
a.对于上述所提的操作,要求对其内部结构进行动画展示,动画可以分步骤进行,可整体进行,或者两者间切换;
b.伪代码跟随动画进程显示。即对于所选择的操作,要求在界面区域展示伪代码,随动画进程高亮显示当前运行步骤所需的代码。

#include <iostream>
#include "mainwindow.h"
#include"PerformanceTestingWidget.h"
#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include<QCheckBox>
#include <QPushButton>
#include <QButtonGroup>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QRandomGenerator>
#include<QInputDialog>

mainwindow::mainwindow(QWidget* parent)
	: QMainWindow(parent),
	inputted(false),
	confirmed(false),
	range(0),
	sortwidgets()
{
	QWidget* mainwidget = new QWidget(this);
	setCentralWidget(mainwidget);

	//页面布局
	QHBoxLayout* centerLayout = new QHBoxLayout(mainwidget);
	mainwidget->setLayout(centerLayout);
	QVBoxLayout* leftLayout = new QVBoxLayout;
	QWidget* rightWidget = new QWidget;
	rightWidget->setFixedSize(1200, 823);
	centerLayout->addLayout(leftLayout);
	centerLayout->addWidget(rightWidget);

	//左侧布局
	QPushButton* inputButton = new QPushButton("Input Array", mainwidget);
	leftLayout->addWidget(inputButton);

	QHBoxLayout* lengthLayout = new QHBoxLayout;
	leftLayout->addLayout(lengthLayout);
	QLabel* lengthLabel = new QLabel("Array Length:", mainwidget);
	lengthInput = new QLineEdit(mainwidget);
	lengthLayout->addWidget(lengthLabel);
	lengthLayout->addWidget(lengthInput);

	QHBoxLayout* rangeLayout = new QHBoxLayout;
	leftLayout->addLayout(rangeLayout);
	QLabel* rangeLabel = new QLabel("Array Range:", mainwidget);
	rangeInput = new QLineEdit(mainwidget);
	rangeLayout->addWidget(rangeLabel);
	rangeLayout->addWidget(rangeInput);

	QGridLayout* SortbuttonLayout = new QGridLayout;
	leftLayout->addLayout(SortbuttonLayout);
	bubbleSortButton = new QCheckBox("Bubble Sort", mainwidget);
	quickSortButton = new QCheckBox("Quick Sort", mainwidget);
	insertionSortButton = new QCheckBox("Insertion Sort", mainwidget);
	shellSortButton = new QCheckBox("Shell Sort", mainwidget);
	selectionSortButton = new QCheckBox("Selection Sort", mainwidget);
	heapSortButton = new QCheckBox("Heap Sort", mainwidget);
	SortbuttonLayout->addWidget(bubbleSortButton, 0, 0);
	SortbuttonLayout->addWidget(quickSortButton, 0, 1);
	SortbuttonLayout->addWidget(insertionSortButton, 1, 0);
	SortbuttonLayout->addWidget(shellSortButton, 1, 1);
	SortbuttonLayout->addWidget(selectionSortButton, 2, 0);
	SortbuttonLayout->addWidget(heapSortButton, 2, 1);

	QHBoxLayout* CRbuttonLayout = new QHBoxLayout; 
	leftLayout->addLayout(CRbuttonLayout);
	QPushButton* confirmButton = new QPushButton("Confirm", mainwidget);
	QPushButton* resetButton = new QPushButton("Reset", mainwidget);
	playButton = new QPushButton("Play All", mainwidget);
	CRbuttonLayout->addWidget(confirmButton);
	CRbuttonLayout->addWidget(resetButton);
	leftLayout->addWidget(playButton);
	Interval = new QLabel("Interval: 1000 ms");
	Interval->setFixedHeight(20);
	Interval->setFixedWidth(110);
	slider = new QSlider(this); 
	slider->setMinimum(0);
	slider->setMaximum(3000);
	slider->setValue(1000); 
	slider->setOrientation(Qt::Horizontal);
	leftLayout->addWidget(Interval);
	leftLayout->addWidget(slider);
	QWidget* widget = new QWidget(this);
	QVBoxLayout* widgetlayout = new QVBoxLayout;
	widget->setLayout(widgetlayout);
	leftLayout->addWidget(widget);
	PerformanceTestingWidget* PTwidget = new PerformanceTestingWidget(this);
	widgetlayout->addWidget(PTwidget);

	//右侧布局
	rightLayout = new QGridLayout;
	rightWidget->setLayout(rightLayout);

	//链接槽函数
	connect(inputButton, &QPushButton::clicked, this, &mainwindow::inputArray);
	connect(bubbleSortButton, &QCheckBox::clicked, this, &mainwindow::sortSelection);
	connect(quickSortButton, &QCheckBox::clicked, this, &mainwindow::sortSelection);
	connect(insertionSortButton, &QCheckBox::clicked, this, &mainwindow::sortSelection);
	connect(shellSortButton, &QCheckBox::clicked, this, &mainwindow::sortSelection);
	connect(selectionSortButton, &QCheckBox::clicked, this, &mainwindow::sortSelection);
	connect(heapSortButton, &QCheckBox::clicked, this, &mainwindow::sortSelection);
	connect(confirmButton, &QPushButton::clicked, this, &mainwindow::confirm);
	connect(resetButton, &QPushButton::clicked, this, &mainwindow::reset);
	connect(playButton, &QPushButton::clicked, this, &mainwindow::play);
	connect(slider, &QSlider::valueChanged, this, &mainwindow::setSpeed);
}

void mainwindow::inputArray()
{
	bool ok;
	QString arrayString = QInputDialog::getText(this, "InputDialog", "Input an array separated by spaces: ", QLineEdit::Normal, QString(), &ok);
	if (ok)
	{
		inputted = true;
		QStringList stringList = arrayString.split(" ");
		int max = 0;
		array.clear();
		for (const QString& str : stringList)
		{
			bool ok1;
			int intValue = str.toInt(&ok1);
			if (ok1) {
				if (intValue > max)
					max = intValue;
				array.append(intValue);
			}
		}

		range = ((max / 10) + 1) * 10;

		lengthInput->setText("Entered");
		rangeInput->setText("Entered");
		lengthInput->setReadOnly(true);
		rangeInput->setReadOnly(true);
	}
}

void mainwindow::confirm()
{
	if (!inputted) {
		QString lengthStr = lengthInput->text();
		QString rangeStr = rangeInput->text();

		bool ok;
		int length = lengthStr.toInt(&ok);
		if (!ok || length <= 0) {
			std::cout << "Invalid length input" << std::endl;
			return;
		}

		range = rangeStr.toInt(&ok);
		if (!ok || range <= 0) {
			std::cout << "Invalid range input" << std::endl;
			return;
		}

		array.clear();
		array.reserve(length);

		for (int i = 0; i < length; ++i) {
			int randomNumber = QRandomGenerator::global()->bounded(0, range);
			array.append(randomNumber);
		}

		confirmed = true;
		sortSelection();
	}
	else {
		confirmed = true;
		sortSelection();
	}
}

void mainwindow::sortSelection()
{
	if (confirmed) {

		while (QLayoutItem* item = rightLayout->takeAt(0)) {
			if (QWidget* widget = item->widget()) {
				rightLayout->removeWidget(widget);
				delete widget;
			}
			else {
				delete item;
			}
		}
		sortingAnimationWidgets.clear();
		codeAnimationWidgets.clear();

		bubbleCAnimation = new BubbleCAW(this);
		quickCAnimation = new QuickCAW(this);
		shellCAnimation = new ShellCAW(this);
		insertionCAnimation = new InsertionCAW(this);
		selectionCAnimation = new SelectionCAW(this);
		heapCAnimation = new HeapCAW(this);

		BubbleSAW* bubbleSAnimation = new BubbleSAW(this, array, range, bubbleCAnimation);
		QuickSAW* quickSAnimation = new QuickSAW(this, array, range, quickCAnimation);
		ShellSAW* shellSAnimation = new ShellSAW(this, array, range, shellCAnimation);
		InsertionSAW* insertionSAnimation = new InsertionSAW(this, array, range, insertionCAnimation);
		SelectionSAW* selectionSAnimation = new SelectionSAW(this, array, range, selectionCAnimation);
		HeapSAW* heapSAnimation = new HeapSAW(this, array, range, heapCAnimation);

		if (bubbleSortButton->isChecked()) {
			sortingAnimationWidgets.append(bubbleSAnimation);
			codeAnimationWidgets.append(bubbleCAnimation);
		}
		if (quickSortButton->isChecked()) {
			sortingAnimationWidgets.append(quickSAnimation);
			codeAnimationWidgets.append(quickCAnimation);
		}
		if (insertionSortButton->isChecked()) {
			sortingAnimationWidgets.append(insertionSAnimation);
			codeAnimationWidgets.append(insertionCAnimation);
		}
		if (shellSortButton->isChecked()) {
			sortingAnimationWidgets.append(shellSAnimation);
			codeAnimationWidgets.append(shellCAnimation);
		}
		if (selectionSortButton->isChecked()) {
			sortingAnimationWidgets.append(selectionSAnimation);
			codeAnimationWidgets.append(selectionCAnimation);
		}
		if (heapSortButton->isChecked()) {
			sortingAnimationWidgets.append(heapSAnimation);
			codeAnimationWidgets.append(heapCAnimation);
		}
		int i = 0;
		for (SortingAnimationWidget* widget : sortingAnimationWidgets) {
			widget->playButton->setVisible(true);
			widget->label->setVisible(true);
			rightLayout->addWidget(widget, i / 4, i % 4);
			i = i + 2;
		}
		i = 1;
		for (CodeAnimationWidget* widget : codeAnimationWidgets) {
			widget->setVisible(true);
			rightLayout->addWidget(widget, i / 4, i % 4);
			i = i + 2;
		}
	}
}

void mainwindow::reset()
{
	array.clear();
	lengthInput->clear();
	rangeInput->clear();
	lengthInput->setReadOnly(false);
	rangeInput->setReadOnly(false);
	inputted = false;
	confirmed = false;
	Interval->setText("Interval: 1000 ms");
	slider->setValue(1000);
	while (QLayoutItem* item = rightLayout->takeAt(0)) {
		if (QWidget* widget = item->widget()) {
			rightLayout->removeWidget(widget);
			delete widget;
		}
		else {
			delete item;
		}
	}
	sortingAnimationWidgets.clear();
	codeAnimationWidgets.clear();
	bubbleSortButton->setChecked(false);
	quickSortButton->setChecked(false);
	insertionSortButton->setChecked(false);
	shellSortButton->setChecked(false);
	selectionSortButton->setChecked(false);
	heapSortButton->setChecked(false);
}

void mainwindow::play() {
	for (SortingAnimationWidget* widget : sortingAnimationWidgets) {
		widget->startAnimation();
	}
	playButton->disconnect();
	playButton->setText("Stop All");
	connect(playButton, &QPushButton::clicked, this, &mainwindow::stop);
}

void mainwindow::stop() {
	for (SortingAnimationWidget* widget : sortingAnimationWidgets) {
		widget->stopAnimation();
	}
	playButton->disconnect();
	playButton->setText("Play All");
	connect(playButton, &QPushButton::clicked, this, &mainwindow::play);
}

void mainwindow::setSpeed(int value) {
	QString Intervalstring = "Interval: ";
	Intervalstring.append(QString::number(value));
	Intervalstring.append(" ms");
	Interval->setText(Intervalstring);
	for (SortingAnimationWidget* widget : sortingAnimationWidgets)
	{
		widget->timer.setInterval(value);
	}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐