八大排序算法的实现与动画理解

5 篇文章 0 订阅

学习说明

本文章采用C语言实现八大经典排序算法,分别是冒泡、插入、选择、归并、希尔、快速、堆、基数排序;并采用Vue3结合element-plus与echarts实现在线动画演示排序过程,帮助理解算法原理与对比算法排序效果

C语言实现排序算法

可以查看该篇文章进行了解,也可以在末尾下载源码进行相应学习;本文章着重讲解在线演示的动画系统

C语言控制台版本的演示效果

在这里插入图片描述

动态排序网站演示效果

原理演示
在这里插入图片描述
在这里插入图片描述

性能演示
在这里插入图片描述

C语言控制台源码

MySort.h

#include <iostream>
#include <stdio.h>
#include <time.h>
#include <Windows.h>
using namespace std;

#define N 10000

typedef int elementType;

#pragma once
class MySort
{
public:
	MySort();

	void bubbleSortTest();
	void insertSortTest();
	void selectSortTest();
	void mergeSortTest();
	void heapSortTest();
	void quickSortTest();
	void shellSortTest();
	void radixSortTest();

	void generateData();

private:
	elementType* arr = (elementType*)malloc(sizeof(elementType) * N);
	elementType* tempArr = (elementType*)malloc(sizeof(elementType) * N);
	elementType** radixSortTempArr;
	int maxDigitLength = 0;
	int calCount = 0;

	void bubbleSort();
	void insertSort();
	void selectSort();
	void mergeSort(int start, int end);
	void heapSort();
	void quickSort(int low, int high);
	void shellSort();
	void radixSort();

	void merge(int start, int mid, int end);
	void heapAdjust(int low, int high);
	int partition(int low, int high);

	int getmaxLength();
	int getDigit(elementType num, int i);
	void clearZero();

	void initData();
	void saveData();
	long getCurrentMillSecond();
};

MySort.cpp

#include "MySort.h"

MySort::MySort()
{
	radixSortTempArr = (elementType**)malloc(sizeof(elementType) * 10);
	if (radixSortTempArr == NULL)
	{
		cout << "内存不足,空间分配出错";
		return;
	}
	for (int i = 0; i < 10; i++)
	{
		radixSortTempArr[i] = (elementType*)malloc(sizeof(elementType) * N);
		if (radixSortTempArr[i] == NULL)
		{
			cout << "内存不足,空间分配出错";
			return;
		}
	}
}

void MySort::bubbleSortTest()
{
	initData();
	long start = getCurrentMillSecond();
	bubbleSort();
	long end = getCurrentMillSecond();
	cout << "冒泡排序耗时:" << (end - start) << endl;
	cout << "冒泡排序运算次数:" << calCount << endl;
	saveData();
}

void MySort::insertSortTest()
{
	initData();
	long start = getCurrentMillSecond();
	insertSort();
	long end = getCurrentMillSecond();
	cout << "插入排序耗时:" << (end - start) << endl;
	cout << "插入排序运算次数:" << calCount << endl;
	saveData();
}

void MySort::selectSortTest()
{
	initData();
	long start = getCurrentMillSecond();
	selectSort();
	long end = getCurrentMillSecond();
	cout << "选择排序耗时:" << (end - start) << endl;
	cout << "选择排序运算次数:" << calCount << endl;
	saveData();
}

void MySort::mergeSortTest()
{
	initData();
	long start = getCurrentMillSecond();
	mergeSort(0, N - 1);
	long end = getCurrentMillSecond();
	cout << "归并排序耗时:" << (end - start) << endl;
	cout << "归并排序运算次数:" << calCount << endl;
	saveData();
}

void MySort::heapSortTest()
{
	initData();
	long start = getCurrentMillSecond();
	heapSort();
	long end = getCurrentMillSecond();
	cout << "堆排序耗时:" << (end - start) << endl;
	cout << "堆排序运算次数:" << calCount << endl;
	saveData();
}

void MySort::quickSortTest()
{
	initData();
	long start = getCurrentMillSecond();
	quickSort(0, N - 1);
	long end = getCurrentMillSecond();
	cout << "快速排序耗时:" << (end - start) << endl;
	cout << "快速排序运算次数:" << calCount << endl;
	saveData();
}

void MySort::shellSortTest()
{
	initData();
	long start = getCurrentMillSecond();
	shellSort();
	long end = getCurrentMillSecond();
	cout << "希尔排序耗时:" << (end - start) << endl;
	cout << "希尔排序运算次数:" << calCount << endl;
	saveData();
}

void MySort::radixSortTest()
{
	initData();
	long start = getCurrentMillSecond();
	radixSort();
	long end = getCurrentMillSecond();
	cout << "基数排序耗时:" << (end - start) << endl;
	cout << "基数排序运算次数:" << calCount << endl;
	saveData();
}

void MySort::generateData()
{
	int* arr = (int*)malloc(sizeof(int) * N);
	if (arr == NULL)
	{
		cout << "内存不足,空间分配出错";
		return;
	}
	srand((unsigned int)time(0));
	for (int i = 0; i < N; i++)
	{
		arr[i] = rand() % N + N;
	}

	FILE* fp = NULL;
	errno_t err;
	if ((err = fopen_s(&fp, "D:/test.txt", "w")) != 0)
	{
		cout << "文件写入失败" << endl;
		return;
	}
	for (int i = 0; i < N; i++)
	{
		fprintf_s(fp, "%d ", arr[i]);
	}
	fclose(fp);
}

void MySort::bubbleSort()
{
	for (int i = 0; i < N; i++)
	{
		for (int j = 1; j < N - i; j++)
		{
			if (arr[j] < arr[j - 1])
			{
				elementType temp = arr[j];
				arr[j] = arr[j - 1];
				arr[j - 1] = temp;
				calCount++;
			}
		}
	}
}

void MySort::insertSort()
{
	for (int i = 1; i < N; i++)
	{
		elementType temp = arr[i];
		int j = i;
		while (j > 0 && temp < arr[j - 1])
		{
			arr[j] = arr[j - 1];
			j--;
			calCount++;
		}
		if (j != i)
		{
			arr[j] = temp;
		}
	}
}

void MySort::selectSort()
{
	int minIndex;
	for (int i = 0; i < N; i++)
	{
		minIndex = i;
		for (int j = i + 1; j < N; j++)
		{
			if (arr[minIndex] > arr[j])
			{
				minIndex = j;
			}
			calCount++;
		}
		if (minIndex != i)
		{
			elementType temp = arr[minIndex];
			arr[minIndex] = arr[i];
			arr[i] = temp;
		}
	}
}

void MySort::mergeSort(int start, int end)
{
	if (start >= end)
	{
		return;
	}
	int mid = (start + end) / 2;
	mergeSort(start, mid);
	mergeSort(mid + 1, end);
	merge(start, mid, end);
}

void MySort::heapSort()
{
	for (int i = N / 2; i >= 0; i--)
	{
		heapAdjust(i, N);
	}

	for (int i = N - 1; i > 0; i--)
	{
		elementType temp = arr[0];
		arr[0] = arr[i];
		arr[i] = temp;
		heapAdjust(0, i - 1);
	}
}

void MySort::quickSort(int low, int high)
{
	if (low < high)
	{
		int pivot = partition(low, high);
		quickSort(low, pivot - 1);
		quickSort(pivot + 1, high);
	}
}

void MySort::shellSort()
{
	for (int step = N / 2; step >= 1; step /= 2)
	{
		for (int i = step; i < N; i++)
		{
			elementType temp = arr[i];
			int j = i;
			while (j >= step && temp < arr[j - step])
			{
				arr[j] = arr[j - step];
				j -= step;
				calCount++;
			}
			if (j != i)
			{
				arr[j] = temp;
			}
		}
	}
}

void MySort::radixSort()
{
	int i, j, l, digit;
	maxDigitLength = getmaxLength();
	int index[10]{};

	for (i = 1; i <= maxDigitLength; i++)
	{
		for (j = 0; j < N; j++)
		{
			digit = getDigit(arr[j], i);
			radixSortTempArr[digit][index[digit]++] = arr[j];
			calCount++;
		}
		l = 0;
		for (j = 0; j < 10; j++)
		{
			int tempIndex = 0;
			while (index[j] > 0)
			{
				arr[l++] = radixSortTempArr[j][tempIndex++];
				index[j]--;
				calCount++;
			}
		}
	}
}

void MySort::merge(int start, int mid, int end)
{
	int k = 0;
	int i = start;
	int  j = mid + 1;
	while (i <= mid && j <= end)
	{
		if (arr[i] <= arr[j])
		{
			tempArr[k++] = arr[i++];
			calCount++;
		}
		else
		{
			tempArr[k++] = arr[j++];
			calCount++;
		}
	}

	while (i <= mid)
	{
		tempArr[k++] = arr[i++];
		calCount++;
	}
	while (j <= end)
	{
		tempArr[k++] = arr[j++];
		calCount++;
	}

	for (int i = 0, j = start; i < k; i++, j++)
	{
		arr[j] = tempArr[i];
	}
}

void MySort::heapAdjust(int low, int high)
{
	elementType temp = arr[low];
	for (int i = 2 * low; i < high; i *= 2)
	{
		if (i < high && arr[i] < arr[i + 1])
		{
			i++;
		}
		if (temp >= arr[i])
		{
			break;
		}
		arr[low] = arr[i];
		low = i;
		calCount++;
	}
	arr[low] = temp;
}

int MySort::partition(int low, int high)
{
	elementType temp = arr[low];
	elementType pivot = arr[low];
	while (low < high)
	{
		while (low < high && arr[high] >= pivot)
		{
			calCount++;
			high--;
		}
		arr[low] = arr[high];
		while (low < high && arr[low] <= pivot)
		{
			calCount++;
			low++;
		}
		arr[high] = arr[low];
	}
	arr[low] = temp;
	return low;
}

int MySort::getmaxLength()
{
	int i;
	int max = 0;
	int count;
	elementType temp;
	for (i = 0; i < N; i++)
	{
		count = 0;
		temp = arr[i];
		while (temp >= 1)
		{
			temp /= 10;
			count++;
		}
		if (count > max)
		{
			max = count;
		}
	}
	return max;
}

int MySort::getDigit(elementType num, int i)
{
	while (i > 1)
	{
		num /= 10;
		i--;
	}
	return num % 10;
}

void MySort::clearZero()
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < N; j++)
		{
			radixSortTempArr[i][j] = 0;
		}
	}
}

void MySort::initData()
{
	calCount = 0;
	FILE* fp = NULL;
	errno_t err;
	if ((err = fopen_s(&fp, "D:/test.txt", "r")) != 0)
	{
		cout << "文件打开失败" << endl;
		return;
	}
	for (int i = 0; i < N; i++)
	{
		fscanf_s(fp, "%d ", &arr[i]);
	}
	fclose(fp);
}

void MySort::saveData()
{
	FILE* fp = NULL;
	errno_t err;
	if ((err = fopen_s(&fp, "D:/sort.txt", "w")) != 0)
	{
		cout << "文件打开失败" << endl;
		return;
	}
	for (int i = 0; i < N; i++)
	{
		fprintf_s(fp, "%d ", arr[i]);
	}
	fclose(fp);
}

long MySort::getCurrentMillSecond()
{
	time_t tt;
	time(&tt);
	SYSTEMTIME t1;
	GetSystemTime(&t1);
	return (long)tt * 1000 + (long)t1.wMilliseconds;
}

main.cpp

#include "MySort.h"

void printMenu()
{
	cout << "***********排序演示及性能测试系统***********" << endl << endl;
	cout << "***************1、冒泡排序*****************" << endl << endl;
	cout << "***************2、插入排序*****************" << endl << endl;
	cout << "***************3、选择排序*****************" << endl << endl;
	cout << "***************4、归并排序*****************" << endl << endl;
	cout << "***************5、快速排序*****************" << endl << endl;
	cout << "***************6、希尔排序*****************" << endl << endl;
	cout << "***************7、堆排序*****************" << endl << endl;
	cout << "***************8、基数排序*****************" << endl << endl;
	cout << "***************9、生成数据*****************" << endl << endl;
	cout << "***************10、退出系统*****************";
}

int main()
{
	int choice;
	MySort mySort;
	bool flag = true;
	printMenu();
	while (flag)
	{
		cout << endl << endl << "请输入你的选择:";
		cin >> choice;
		switch (choice)
		{
		case 1:
			mySort.bubbleSortTest();
			break;
		case 2:
			mySort.insertSortTest();
			break;
		case 3:
			mySort.selectSortTest();
			break;
		case 4:
			mySort.mergeSortTest();
			break;
		case 5:
			mySort.quickSortTest();
			break;
		case 6:
			mySort.shellSortTest();
			break;
		case 7:
			mySort.heapSortTest();
			break;
		case 8:
			mySort.radixSortTest();
			break;
		case 9:
			mySort.generateData();
			break;
		case 10:
			flag = false;
			break;
		default:
			break;
		}
	}
	system("pause");
}

在线网站关键代码

PrincipleDisplay.vue

<template>
    <div>
        <el-button @click="startSort('Bubble')">冒泡排序</el-button>
        <el-button @click="startSort('Insert')">插入排序</el-button>
        <el-button @click="startSort('Select')">选择排序</el-button>
        <el-button @click="startSort('Merge')">归并排序</el-button>
        <el-button @click="startSort('Shell')">希尔排序</el-button>
        <el-button @click="startSort('Quick')">快速排序</el-button>
        <el-button @click="startSort('Heap')">堆排序</el-button>
        <el-button @click="startSort('Radix')">基数排序</el-button>
        <el-button type="primary" @click="getRandomArray">随机生成数据</el-button>
        <el-input placeholder="数据个数" style="width: 120px; margin-left: 10px;" v-model="data.count" />
    </div>

    <el-input placeholder="数组形式输入数据,按Enter结束输入,按空格划分,如(1 2 3 4 5 9 8 7 6 10)" style="margin-top: 20px;"
        v-model="data.inputArr" @keypress.enter="getArrByInput" />

    <div id="chartContainer"></div>
</template>

<script>
import { onMounted, reactive } from "vue";
import { bubbleSort, getRandomArr, heapSort, initChart, insertSort, judgeArrSortOverOrNotStart, judgeArrValid, mergeSort, message, quickSort, radixSort, selectSort, shellSort } from '@/utils/api';

export default {
    name: "PrincipleDisplay",
    setup() {
        const data = reactive({
            arr: [],
            arrData: [11, 3, 5, 7, 9, 2, 4, 6, 8, 10],
            count: 30,
            inputArr: "",
        });
        function changeArrToColorArr(arr) {
            const colorArr = [];
            for (var i = 0; i < arr.length; i++) {
                colorArr.push({
                    value: arr[i],
                    itemStyle: {
                        color: '#5470c6'
                    },
                });
            }
            return colorArr;
        }
        
        function startSort(sortType) {
            if (!judgeArrSortOverOrNotStart(data.arr)) {
                message("数组排序演示还未完成", "info");
                return;
            }
            data.arr = changeArrToColorArr(data.arrData);
            switch (sortType) {
                case "Bubble":
                    bubbleSort(data.arr);
                    break;
                case "Insert":
                    insertSort(data.arr);
                    break;
                case "Select":
                    selectSort(data.arr);
                    break;
                case "Merge":
                    mergeSort(data.arr);
                    break;
                case "Shell":
                    shellSort(data.arr);
                    break;
                case "Quick":
                    quickSort(data.arr);
                    break;
                case "Heap":
                    heapSort(data.arr);
                    break;
                case "Radix":
                    radixSort(data.arr);
                    break;
                default:
                    break;
            }
        }
        onMounted(() => {
            data.arr = changeArrToColorArr(data.arrData);
            initChart(data.arr);
        });
        function getRandomArray() {
            if (!judgeArrSortOverOrNotStart(data.arr)) {
                message("数组排序演示还未完成", "info");
                return;
            }
            if (data.count > 30) {
                message("数组元素个数过多, 展示消耗时间过长", "info");
                return;
            }
            data.arrData = getRandomArr(data.count);
            data.arr = changeArrToColorArr(data.arrData);
            initChart(data.arr);
        }
        function getArrByInput() {
            if (!judgeArrSortOverOrNotStart(data.arr)) {
                message("数组排序演示还未完成", "info");
                return;
            }
            const arr = data.inputArr.split(" ");
            if (Array.isArray(arr)) {
                if (arr.length < 2) {
                    message("输入数组元素个数过少", "info");
                } else if (!judgeArrValid(arr)) {
                    message("数组元素差距过大, 绘制图像不直观", "info");
                } else {
                    data.arrData = arr;
                    data.arr = changeArrToColorArr(data.arrData);
                    initChart(data.arr);
                }
            } else {
                message("输入数组有误, 不是正确的数组", "info");
            }
        }

        return {
            data,
            startSort,
            getRandomArray,
            getArrByInput,
        }
    },
};
</script>

<style scoped>
#chartContainer {
    width: calc(100vw - 80px);
    height: calc(100vh - 230px);
    position: absolute;
    top: 130px;
}
</style>

PerformanceDisplay.vue

<template>
    <div>
        <el-button @click="getSortPerformance(1000)">1000个数据</el-button>
        <el-button @click="getSortPerformance(5000)">5000个数据</el-button>
        <el-button @click="getSortPerformance(10000)">10000个数据</el-button>
        <el-button @click="getSortPerformance(50000)">50000个数据</el-button>
        <el-button @click="getSortPerformance(100000)">100000个数据</el-button>
        <el-button @click="getSortPerformance(300000)">300000个数据</el-button>
        <el-button @click="getSortPerformance(500000)">500000个数据</el-button>
        <el-button @click="getSortPerformance(1000000)">1000000个数据</el-button>
    </div>

    <div id="squareChartContainer"></div>
    <div id="logChartContainer"></div>
</template>

<script>
import { onBeforeMount } from "vue";
import { getEightSortPerformance, getFiveLogSortPerformance } from "@/utils/sort.js"

export default {
    name: "PerformanceDisplay",
    setup() {
        onBeforeMount(() => {

        });
        function getSortPerformance(count) {
            switch (count) {
                case 1000:
                case 5000:
                case 10000:
                    getEightSortPerformance(count);
                    break;
                case 50000:
                case 100000:
                case 300000:
                case 500000:
                case 1000000:
                    getFiveLogSortPerformance(count);
                    break;
            }
        }
        return {
            getSortPerformance,
        };
    },
};
</script>

<style scoped>
#squareChartContainer {
    width: calc(37.5vw - 60px);
    height: calc(100vh - 200px);
    position: absolute;
    top: 90px;
    /* border: 1px black solid; */
}
#logChartContainer {
    width: calc(62.5vw - 60px);
    height: calc(100vh - 200px);
    position: absolute;
    top: 90px;
    right: 20px;
    /* border: 1px black solid; */
}
</style>

api.js

import { ElMessage } from 'element-plus';
import * as echarts from "echarts";

export function message(msg, type) {
    ElMessage({
        message: msg,
        showClose: true,
        type: type,
        center: true
    })
}

export const getRandomArr = (count) => {
    const arr = [];
    for (var i = 0; i < count; i++) {
        arr.push(Math.floor(Math.random() * (count)) + 1);
    }
    return arr;
}

export const judgeArrValid = (arr) => {
    var min = arr[0];
    var max = arr[0];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
        if (arr[i] < min) {
            min = arr[i];
        }
    }
    if (max / min > 50) {
        return false;
    }
    return true;
}

export const judgeArrSortOverOrNotStart = (arr) => {
    var startFlag = true;
    var overFlag = true;
    var i;
    for (i = 0; i < arr.length; i++) {
        if (arr[i].itemStyle.color != "#5470c6") {
            overFlag = false;
        }
    }
    for (i = 0; i < arr.length; i++) {
        if (arr[i].itemStyle.color != "#a90000") {
            startFlag = false;
        }
    }
    return startFlag || overFlag;
}

export const initChart = (arr) => {
    const chartDom = document.getElementById("chartContainer");
    const myChart = echarts.init(chartDom);
    const option = {
        xAxis: {
            type: "category",
        },
        yAxis: {
            type: "value",
        },
        series: [
            {
                data: arr,
                type: "bar",
            },
        ],
        grid: {
            left: "1%",
            right: "1%",
            bottom: "2%",
            containLabel: true,
        },
    };

    option && myChart.setOption(option);
}

const interval = 500;
function sleep() {
    return new Promise(resolve => setTimeout(resolve, interval));
}

export const bubbleSort = async (arr) => {
    for (var i = 0; i < arr.length; i++) {
        for (var j = 1; j < arr.length - i; j++) {
            arr[j].itemStyle = {
                color: '#a90000'
            };
            arr[j - 1].itemStyle = {
                color: '#a90000'
            };
            if (arr[j].value < arr[j - 1].value) {
                var temp = arr[j].value;
                arr[j].value = arr[j - 1].value;
                arr[j - 1].value = temp;
            }
            await sleep();
            initChart(arr);
            arr[j - 1].itemStyle = {
                color: '#5470c6'
            };
        }
    }
    arr[0].itemStyle = {
        color: '#a90000'
    };
}

export const insertSort = async (arr) => {
    for (var i = 0; i < arr.length; i++) {
        var temp = arr[i].value;
        var j = i;
        arr[i].itemStyle = {
            color: '#a90000'
        };
        while (j > 0 && temp < arr[j - 1].value) {
            arr[j].value = arr[j - 1].value;
            j--;
            await sleep();
            initChart(arr);
        }
        if (j != i) {
            arr[j].value = temp;
        }
    }
}

export const selectSort = async (arr) => {
    var minIndex;
    for (var i = 0; i < arr.length; i++) {
        minIndex = i;
        for (var j = i + 1; j < arr.length; j++) {
            if (arr[minIndex].value > arr[j].value) {
                minIndex = j;
                arr[minIndex].itemStyle = {
                    color: '#a90000'
                };
                await sleep();
                initChart(arr);
            }
        }
        arr[minIndex].itemStyle = {
            color: '#5470c6'
        };
        if (minIndex != i) {
            var temp = arr[minIndex].value;
            arr[minIndex].value = arr[i].value;
            arr[i].value = temp;
        }
        arr[i].itemStyle = {
            color: '#a90000'
        };
    }
    await sleep();
    initChart(arr);
}

export const mergeSort = async (arr) => {
    const tempArr = [];
    for (var i = 0; i < arr.length; i++) {
        tempArr.push(0);
    }
    mergeSortStart(arr, tempArr, 0, arr.length - 1);
}

async function mergeSortStart(arr, tempArr, start, end) {
    if (start >= end) {
        return;
    }
    var mid = Math.floor((start + end) / 2);
    await mergeSortStart(arr, tempArr, start, mid);
    await mergeSortStart(arr, tempArr, mid + 1, end);
    await merge(arr, tempArr, start, mid, end);
    await sleep();
    initChart(arr);
}

async function merge(arr, tempArr, start, mid, end) {
    var k = 0;
    var i = start;
    var j = mid + 1;
    while (i <= mid && j <= end) {
        if (arr[i].value <= arr[j].value) {
            tempArr[k++] = arr[i++].value;
        }
        else {
            tempArr[k++] = arr[j++].value;
        }
    }

    while (i <= mid) {
        tempArr[k++] = arr[i++].value;
    }
    while (j <= end) {
        tempArr[k++] = arr[j++].value;
    }

    for (i = 0, j = start; i < k; i++, j++) {
        arr[j].itemStyle = {
            color: '#a90000'
        };
        arr[j].value = tempArr[i];
    }
}

export const shellSort = async (arr) => {
    for (var step = arr.length / 2; step >= 1;) {
        await recoverColor(arr, "#5470c6");
        for (var i = step; i < arr.length; i++) {
            var temp = arr[i].value;
            var j = i;
            while (j >= step && temp < arr[j - step].value) {
                arr[j].value = arr[j - step].value;
                j -= step;
            }
            if (j != i) {
                arr[j].value = temp;
            }
            arr[i - step].itemStyle = {
                color: '#a90000'
            }
            arr[i].itemStyle = {
                color: '#a90000'
            }
            await sleep();
            initChart(arr);
        }
        step = Math.floor(step / 2);
    }
}

async function recoverColor(arr, color) {
    for (var i = 0; i < arr.length; i++) {
        arr[i].itemStyle = {
            color: color
        }
    }
}

export const quickSort = async (arr) => {
    await quickSortStart(arr, 0, arr.length - 1);
    await recoverColor(arr, "#a90000");
    await sleep();
    initChart(arr);
}

async function quickSortStart(arr, low, high) {
    if (low < high) {
        var pivot = await partition(arr, low, high);
        arr[pivot].itemStyle = {
            color: '#ffd766'
        }
        await sleep();
        initChart(arr);
        await quickSortStart(arr, low, pivot - 1);
        await quickSortStart(arr, pivot + 1, high);
    }
}

async function partition(arr, low, high) {
    var temp = arr[low].value;
    var pivot = arr[low].value;
    while (low < high) {
        while (low < high && arr[high].value >= pivot) {
            high--;
        }
        arr[high].itemStyle = {
            color: '#a90000'
        }
        arr[low].value = arr[high].value;
        while (low < high && arr[low].value <= pivot) {
            low++;
        }
        arr[low].itemStyle = {
            color: '#a90000'
        }
        arr[high].value = arr[low].value;
    }
    arr[low].value = temp;
    return low;
}

export const heapSort = async (arr) => {
    var i;
    for (i = arr.length / 2; i >= 0; i--) {
        await heapAdjust(arr, i, arr.length);
    }

    for (i = arr.length - 1; i >= 0; i--) {
        var temp = arr[0].value;
        arr[0].value = arr[i].value;
        arr[i].value = temp;
        await heapAdjust(arr, 0, i - 1);
        arr[i].itemStyle = {
            color: '#a90000'
        }
    }

    await sleep();
    initChart(arr);
}

async function heapAdjust(arr, low, high) {
    var temp = arr[low].value;
    for (var i = 2 * low; i < high; i *= 2) {
        if (i < high && arr[i].value < arr[i + 1].value) {
            i++;
        }
        if (temp >= arr[i].value) {
            break;
        }
        arr[low].value = arr[i].value;
        low = i;
    }
    arr[low].value = temp;
    await sleep();
    initChart(arr);
}

export const radixSort = async (arr) => {
    var i, j, l, digit;
    const radixSortTempArr = [];
    for (i = 0; i < 10; i++) {
        const tempArr = [];
        for (j = 0; j < arr.length; j++) {
            tempArr.push(0);
        }
        radixSortTempArr.push(tempArr);
    }
    const maxDigitLength = await getmaxLength(arr);
    const index = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

    for (i = 1; i <= maxDigitLength; i++) {
        for (j = 0; j < arr.length; j++) {
            digit = await getDigit(arr[j].value, i);
            radixSortTempArr[digit][index[digit]++] = arr[j].value;
        }
        l = 0;
        for (j = 0; j < 10; j++) {
            var tempIndex = 0;
            while (index[j] > 0) {
                arr[l].value = radixSortTempArr[j][tempIndex++];
                index[j]--;
                arr[l].itemStyle = {
                    color: '#a90000'
                }
                l++;
                await sleep();
                initChart(arr);
            }
        }
        await clearZero(radixSortTempArr);
    }
}

async function getmaxLength(arr) {
    var max = 0, count, temp;
    for (var i = 0; i < arr.length; i++) {
        count = 0;
        temp = arr[i].value;
        while (temp >= 1) {
            temp /= 10;
            count++;
        }
        if (count > max) {
            max = count;
        }
    }
    return max;
}

async function getDigit(num, i) {
    while (i > 1) {
        num = Math.floor(num / 10);
        i--;
    }
    return num % 10;
}

async function clearZero(radixSortTempArr) {
    for (var i = 0; i < 10; i++) {
        for (var j = 0; j < radixSortTempArr[0].length; j++) {
            radixSortTempArr[i][j] = 0;
        }
    }
}

sort.js

import { getRandomArr } from "./api"
import * as echarts from "echarts";

export const initSquareChart = (seriesSquareData) => {
    const chartDom = document.getElementById("squareChartContainer");
    const myChart = echarts.init(chartDom);
    const option = {
        xAxis: {
            type: "category",
        },
        yAxis: {
            type: "value",
        },
        legend: {
            data: ['冒泡排序', '插入排序', '选择排序']
        },
        tooltip: {
            trigger: 'axis'
        },
        series: seriesSquareData,
        grid: {
            left: "1%",
            right: "1%",
            bottom: "2%",
            containLabel: true,
        },
    };

    option && myChart.setOption(option);
}

export const initLogChart = (seriesSquareData) => {
    const chartDom = document.getElementById("logChartContainer");
    const myChart = echarts.init(chartDom);
    const option = {
        xAxis: {
            type: "category",
        },
        yAxis: {
            type: "value",
        },
        legend: {
            data: ['归并排序', '希尔排序', '快速排序', '堆排序', '基数排序']
        },
        tooltip: {
            trigger: 'axis'
        },
        series: seriesSquareData,
        grid: {
            left: "1%",
            right: "1%",
            bottom: "2%",
            containLabel: true,
        },
    };

    option && myChart.setOption(option);
}

const interval = 500;
function sleep() {
    return new Promise(resolve => setTimeout(resolve, interval));
}

export const getEightSortPerformance = async (count) => {
    const arr = getRandomArr(count);
    const seriesSquareData = [];
    seriesSquareData.push({
        name: '冒泡排序',
        type: 'line',
        data: getData(arr, bubbleSort)
    });
    initSquareChart(seriesSquareData);
    await sleep();

    seriesSquareData.push({
        name: '插入排序',
        type: 'line',
        data: getData(arr, insertSort)
    });
    initSquareChart(seriesSquareData);
    await sleep();

    seriesSquareData.push({
        name: '选择排序',
        type: 'line',
        data: getData(arr, selectSort)
    });
    initSquareChart(seriesSquareData);
    await sleep();

    const seriesLogData = [];
    seriesLogData.push({
        name: '归并排序',
        type: 'line',
        data: getData(arr, mergeSort)
    });
    initLogChart(seriesLogData);
    await sleep();

    seriesLogData.push({
        name: '希尔排序',
        type: 'line',
        data: getData(arr, shellSort)
    });
    initLogChart(seriesLogData);
    await sleep();

    seriesLogData.push({
        name: '快速排序',
        type: 'line',
        data: getData(arr, quickSort)
    });
    initLogChart(seriesLogData);
    await sleep();

    seriesLogData.push({
        name: '堆排序',
        type: 'line',
        data: getData(arr, heapSort)
    });
    initLogChart(seriesLogData);
    // await sleep();

    // seriesLogData.push({
    //     name: '基数排序',
    //     type: 'line',
    //     data: getData(arr, radixSort)
    // });
    // initLogChart(seriesLogData);
}

export const getFiveLogSortPerformance = async (count) => {
    const arr = getRandomArr(count);
    const seriesLogData = [];
    seriesLogData.push({
        name: '希尔排序',
        type: 'line',
        data: getData(arr, shellSort)
    });
    initLogChart(seriesLogData);
    await sleep();

    seriesLogData.push({
        name: '快速排序',
        type: 'line',
        data: getData(arr, quickSort)
    });
    initLogChart(seriesLogData);
    await sleep();

    seriesLogData.push({
        name: '堆排序',
        type: 'line',
        data: getData(arr, heapSort)
    });
    initLogChart(seriesLogData);
    await sleep();

    seriesLogData.push({
        name: '归并排序',
        type: 'line',
        data: getData(arr, mergeSort)
    });
    initLogChart(seriesLogData);
    // await sleep();

    // seriesLogData.push({
    //     name: '基数排序',
    //     type: 'line',
    //     data: getData(arr, radixSort)
    // });
    // initLogChart(seriesLogData);
}

const runTimes = 5;
function getData(arr, func) {
    const data = [];
    for (var i = 0; i < runTimes; i++) {
        const tempArr = [];
        arr.forEach(item => tempArr.push(item));
        data.push(func(tempArr));
    }
    return data;
}

function bubbleSort(arr) {
    const start = new Date().getTime();
    for (var i = 0; i < arr.length; i++) {
        for (var j = 1; j < arr.length - i; j++) {
            if (arr[j] < arr[j - 1]) {
                var temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
            }
        }
    }
    const end = new Date().getTime();
    return end - start;
}

function insertSort(arr) {
    const start = new Date().getTime();
    for (var i = 0; i < arr.length; i++) {
        var temp = arr[i];
        var j = i;
        while (j > 0 && temp < arr[j - 1]) {
            arr[j] = arr[j - 1];
            j--;
        }
        if (j != i) {
            arr[j] = temp;
        }
    }
    const end = new Date().getTime();
    return end - start;
}

function selectSort(arr) {
    const start = new Date().getTime();
    var minIndex;
    for (var i = 0; i < arr.length; i++) {
        minIndex = i;
        for (var j = i + 1; j < arr.length; j++) {
            if (arr[minIndex] > arr[j]) {
                minIndex = j;
            }
        }
        if (minIndex != i) {
            var temp = arr[minIndex];
            arr[minIndex] = arr[i];
            arr[i] = temp;
        }
    }
    const end = new Date().getTime();
    return end - start;
}

function mergeSort(arr) {
    const start = new Date().getTime();
    const tempArr = [];
    for (var i = 0; i < arr.length; i++) {
        tempArr.push(0);
    }
    mergeSortStart(arr, tempArr, 0, arr.length - 1);
    const end = new Date().getTime();
    return end - start;
}

function mergeSortStart(arr, tempArr, start, end) {
    if (start >= end) {
        return;
    }
    var mid = Math.floor((start + end) / 2);
    mergeSortStart(arr, tempArr, start, mid);
    mergeSortStart(arr, tempArr, mid + 1, end);
    merge(arr, tempArr, start, mid, end);
}

function merge(arr, tempArr, start, mid, end) {
    var k = 0;
    var i = start;
    var j = mid + 1;
    while (i <= mid && j <= end) {
        if (arr[i] <= arr[j]) {
            tempArr[k++] = arr[i++];
        }
        else {
            tempArr[k++] = arr[j++];
        }
    }
    while (i <= mid) {
        tempArr[k++] = arr[i++];
    }
    while (j <= end) {
        tempArr[k++] = arr[j++];
    }
    for (i = 0, j = start; i < k; i++, j++) {
        arr[j] = tempArr[i];
    }
}

function shellSort(arr) {
    const start = new Date().getTime();
    for (var step = arr.length / 2; step >= 1;) {
        for (var i = step; i < arr.length; i++) {
            var temp = arr[i];
            var j = i;
            while (j >= step && temp < arr[j - step]) {
                arr[j] = arr[j - step];
                j -= step;
            }
            if (j != i) {
                arr[j] = temp;
            }
        }
        step = Math.floor(step / 2);
    }
    const end = new Date().getTime();
    return end - start;
}

function quickSort(arr) {
    const start = new Date().getTime();
    quickSortStart(arr, 0, arr.length - 1);
    const end = new Date().getTime();
    return end - start;
}

function quickSortStart(arr, low, high) {
    if (low < high) {
        var pivot = partition(arr, low, high);
        quickSortStart(arr, low, pivot - 1);
        quickSortStart(arr, pivot + 1, high);
    }
}

function partition(arr, low, high) {
    var temp = arr[low];
    var pivot = arr[low];
    while (low < high) {
        while (low < high && arr[high] >= pivot) {
            high--;
        }
        arr[low] = arr[high];
        while (low < high && arr[low] <= pivot) {
            low++;
        }
        arr[high] = arr[low];
    }
    arr[low] = temp;
    return low;
}

function heapSort(arr) {
    const start = new Date().getTime();
    var i;
    for (i = arr.length / 2; i >= 0; i--) {
        heapAdjust(arr, i, arr.length);
    }
    for (i = arr.length - 1; i >= 0; i--) {
        var temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
        heapAdjust(arr, 0, i - 1);
    }
    const end = new Date().getTime();
    return end - start;
}

function heapAdjust(arr, low, high) {
    var temp = arr[low];
    for (var i = 2 * low; i < high; i *= 2) {
        if (i < high && arr[i] < arr[i + 1]) {
            i++;
        }
        if (temp >= arr[i]) {
            break;
        }
        arr[low] = arr[i];
        low = i;
    }
    arr[low] = temp;
}

export const radixSort = (arr) => {
    const start = new Date().getTime();
    var i, j, l, digit;
    const radixSortTempArr = [];
    for (i = 0; i < 10; i++) {
        const tempArr = [];
        for (j = 0; j < arr.length; j++) {
            tempArr.push(0);
        }
        radixSortTempArr.push(tempArr);
    }
    const maxDigitLength = getmaxLength(arr);
    const index = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

    for (i = 1; i <= maxDigitLength; i++) {
        for (j = 0; j < arr.length; j++) {
            digit = getDigit(arr[j], i);
            radixSortTempArr[digit][index[digit]++] = arr[j];
        }
        l = 0;
        for (j = 0; j < 10; j++) {
            var tempIndex = 0;
            while (index[j] > 0) {
                arr[l++] = radixSortTempArr[j][tempIndex++];
                index[j]--;
            }
        }
        clearZero(radixSortTempArr);
    }
    const end = new Date().getTime();
    return end - start;
}

function getmaxLength(arr) {
    var max = 0, count, temp;
    for (var i = 0; i < arr.length; i++) {
        count = 0;
        temp = arr[i];
        while (temp >= 1) {
            temp /= 10;
            count++;
        }
        if (count > max) {
            max = count;
        }
    }
    return max;
}

function getDigit(num, i) {
    while (i > 1) {
        num = Math.floor(num / 10);
        i--;
    }
    return num % 10;
}

function clearZero(radixSortTempArr) {
    for (var i = 0; i < 10; i++) {
        for (var j = 0; j < radixSortTempArr[0].length; j++) {
            radixSortTempArr[i][j] = 0;
        }
    }
}

附注:代码实际有一些可改进的地方,主要是基数排序和冒泡排序里面的逻辑,可以改进

Gitee源码下载链接

https://gitee.com/anxwefndu/sorting-demonstration-system

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值