c# 排序算法可视化
最近在 b 站上看了一个排序算法的动画,所以想自己写一个类似的项目。
项目使用 Graphics 在 winform 的窗体上绘图。(新建项目时选择控制台项目,注意添加引用:System.Drawing, System.Windows.Forms)
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; namespace Sort
{
/// <summary>
/// 排序算法
/// </summary>
class Program
{
static void Main(string[] args)
{
FrmSort frm = new FrmSort();
frm.ShowDialog();
}
} class FrmSort : Form
{
private const int length = ; //待排序集合的宽度
private const int width = ; //绘图时每个柱子的宽度
private const int height = ; //绘图时每个柱子的高度放大倍数 public FrmSort()
{
this.BackColor = Color.White;
this.Width = ;
this.Height = ;
this.Shown += new System.EventHandler(this.Frm_Shown);
} private void Frm_Shown(object sender, EventArgs e)
{
Insert();
HalfInsert();
SelectSort();
BubbleSort();
ShellSort();
MergeSort();
} //获得随机数组
static List<int> GetRandomList()
{
Random rnd = new Random();
List<int> listOriginal = new List<int>();
for (int i = ; i < (length + ); i++)
{
listOriginal.Add(i);
}
List<int> list = new List<int>();
foreach (int item in listOriginal)
{
list.Insert(rnd.Next(list.Count), item);
}
return list;
} static int[] GetRandomArray()
{
return GetRandomList().ToArray();
} // 绘图
private void Draw(List<int> valueList, List<int> reDrawIndexList, Graphics g, int xBase, int yBase)
{
for (int i = ; i < reDrawIndexList.Count; i++)
{
int xIndex = reDrawIndexList[i];
Pen whitePen = new Pen(Brushes.White, width);
Pen blackPen = new Pen(Brushes.Black, width);
Point point1 = new Point(xBase + xIndex * width, yBase);
Point point2 = new Point(xBase + xIndex * width, yBase + length * height);
Point point3 = new Point(xBase + xIndex * width, yBase + valueList[xIndex] * height);
g.DrawLine(whitePen, point1, point2);
g.DrawLine(blackPen, point1, point3);
}
} // 绘图
private void Draw(int[] valueList, List<int> reDrawIndexList, Graphics g, int xBase, int yBase)
{
for (int i = ; i < reDrawIndexList.Count; i++)
{
int xIndex = reDrawIndexList[i];
Pen whitePen = new Pen(Brushes.White, width);
Pen blackPen = new Pen(Brushes.Black, width);
Point point1 = new Point(xBase + xIndex * width, yBase);
Point point2 = new Point(xBase + xIndex * width, yBase + length * height);
Point point3 = new Point(xBase + xIndex * width, yBase + valueList[xIndex] * height);
g.DrawLine(whitePen, point1, point2);
g.DrawLine(blackPen, point1, point3);
}
} // 绘图
private void Draw(int myValue, int myIndex, Graphics g, int xBase, int yBase)
{
Pen whitePen = new Pen(Brushes.White, width);
Pen blackPen = new Pen(Brushes.Black, width);
Point point1 = new Point(xBase + myIndex * width, yBase);
Point point2 = new Point(xBase + myIndex * width, yBase + length * height);
Point point3 = new Point(xBase + myIndex * width, yBase + myValue * height);
g.DrawLine(whitePen, point1, point2);
g.DrawLine(blackPen, point1, point3);
} private void GetBasePoint(int index, out int xBase, out int yBase)
{
xBase = + (index % ) * width * length * / ;
yBase = + (index / ) * height * length * / ;
} //直接插入
//每一轮都保证左侧序列已排序, 右侧序列不断的往左侧序列中插入
private void Insert(int place)
{
int xBase, yBase;
GetBasePoint(place, out xBase, out yBase);
int[] intArray = GetRandomArray();
using (Graphics g = this.CreateGraphics())
{
List<int> listIndex = new List<int>();
for (int i = ; i < intArray.Length; i++)
{
listIndex.Add(i);
}
Draw(intArray, listIndex, g, xBase, yBase);
for (int i = ; i < intArray.Length; i++)
{
for (int j = i - ; (j >= ) && (intArray[j + ] < intArray[j]); j--)
{
int temp = intArray[j + ];
intArray[j + ] = intArray[j];
intArray[j] = temp;
Draw(intArray[j], j, g, xBase, yBase);
Draw(intArray[j + ], j + , g, xBase, yBase);
}
}
}
} //折半插入
//对直接插入进行优化,在左侧找到最佳的插入点后再插入,而不是按顺序逐个尝试
private void HalfInsert(int place)
{
int xBase, yBase;
GetBasePoint(place, out xBase, out yBase);
List<int> list = GetRandomList();
using (Graphics g = this.CreateGraphics())
{
List<int> listIndex = new List<int>();
for (int i = ; i < list.Count; i++)
{
listIndex.Add(i);
}
Draw(list, listIndex, g, xBase, yBase); for (int i = ; i < list.Count; i++)
{
int temp = list[i];
int low = ;
int high = i - ;
while (low <= high)
{
int mid = (low + high) / ;
if (temp < list[mid])
{
high = mid - ;
}
else
{
low = mid + ;
}
Draw(temp, mid, g, xBase, yBase);
Thread.Sleep();
Draw(list[mid], mid, g, xBase, yBase);
}
int myValue = list[i];
list.RemoveAt(i);
list.Insert(low, myValue);
listIndex.Clear();
for (int j = low; j <= i; j++)
{
listIndex.Add(j);
}
Draw(list, listIndex, g, xBase, yBase);
}
}
} //选择排序
//找出list[0- 99]中的最小值换到list[0]上
//找出list[1- 99]中的最小值换到list[1]上
//最后一轮:找出list[98- 99]中的最小值换到list[98]上
private void SelectSort(int place)
{
int xBase, yBase;
GetBasePoint(place, out xBase, out yBase);
List<int> list = GetRandomList();
using (Graphics g = this.CreateGraphics())
{
List<int> listIndex = new List<int>();
for (int i = ; i < list.Count; i++)
{
listIndex.Add(i);
}
Draw(list, listIndex, g, xBase, yBase);
for (int i = ; i < list.Count; i++)
{
//找出后面的最小值
int miniIndex = i;
int miniValue = list[i];
for (int j = i; j < list.Count; j++)
{
if (list[j] < miniValue)
{
miniIndex = j;
miniValue = list[j];
}
}
//重绘
if (miniIndex > i)
{
list.RemoveAt(miniIndex);
list.Insert(i, miniValue);
for (int j = i; j < miniIndex; j++)
{
Draw(list[j], j, g, xBase, yBase);
}
}
}
}
} //冒泡排序
//第一轮:intArray[0] > intArray[1] ? 交换 : 不变。intArray[1] > intArray[2] ..... intArray[98] > intArray[99] ?
//第二轮:intArray[0] > intArray[1] ? 交换 : 不变。intArray[1] > intArray[2] ..... intArray[97] > intArray[98] ?
//最后一轮:intArray[0] > intArray[1] ?
private void BubbleSort(int place)
{
int xBase, yBase;
GetBasePoint(place, out xBase, out yBase);
int[] intArray = GetRandomArray();
using (Graphics g = this.CreateGraphics())
{
List<int> listIndex = new List<int>();
for (int i = ; i < intArray.Length; i++)
{
listIndex.Add(i);
}
Draw(intArray, listIndex, g, xBase, yBase);
for (int i = intArray.Length; i > ; i--)
{
for (int j = ; j < i - ; j++)
{
if (intArray[j] > intArray[j + ])
{
int temp = intArray[j];
intArray[j] = intArray[j + ];
intArray[j + ] = temp;
Draw(intArray[j], j, g, xBase, yBase);
Draw(intArray[j + ], j + , g, xBase, yBase);
Thread.Sleep();
}
}
}
}
} //希尔排序
private void ShellSort(int place)
{
int xBase, yBase;
GetBasePoint(place, out xBase, out yBase);
int[] intArray = GetRandomArray();
using (Graphics g = this.CreateGraphics())
{
List<int> listIndex = new List<int>();
for (int i = ; i < intArray.Length; i++)
{
listIndex.Add(i);
}
Draw(intArray, listIndex, g, xBase, yBase);
for (int step = intArray.Length / ; step >= ; step = step / ) //增量递减到1使完成排序
{
for (int i = step; i < intArray.Length; i++) //插入排序的一轮
{
int temp = intArray[i];
int j = ;
for (j = i - step; (j >= ) && (intArray[j] > temp); j = j - step)
{
intArray[j + step] = intArray[j];
Draw(intArray[j + step], j + step, g, xBase, yBase);
Thread.Sleep();
}
intArray[j + step] = temp;
Draw(intArray[j + step], j + step, g, xBase, yBase);
}
}
}
} #region 归并排序
public void MergeSort(int place)
{
int xBase, yBase;
GetBasePoint(place, out xBase, out yBase);
int[] intArray = GetRandomArray();
using (Graphics g = this.CreateGraphics())
{
List<int> listIndex = new List<int>();
for (int i = ; i < intArray.Length; i++)
{
listIndex.Add(i);
}
Draw(intArray, listIndex, g, xBase, yBase);
MergeSort(intArray, , intArray.Length - , g, xBase, yBase);
}
} private void MergeSort(int[] array, int p, int r, Graphics g, int xBase, int yBase)
{
if (p < r)
{
int q = (p + r) / ;
MergeSort(array, p, q, g, xBase, yBase);
MergeSort(array, q + , r, g, xBase, yBase);
Merge(array, p, q, r, g, xBase, yBase);
}
} private void Merge(int[] array, int p, int q, int r, Graphics g, int xBase, int yBase)
{
int[] L = new int[q - p + ];
int[] R = new int[r - q + ];
L[q - p + ] = int.MaxValue;
R[r - q] = int.MaxValue; for (int i = ; i < q - p + ; i++)
{
L[i] = array[p + i];
} for (int i = ; i < r - q; i++)
{
R[i] = array[q + + i];
} int j = ;
int k = ;
for (int i = ; i < r - p + ; i++)
{
if (L[j] <= R[k])
{
array[p + i] = L[j];
j++;
}
else
{
array[p + i] = R[k];
k++;
}
Draw(array[p + i], p + i, g, xBase, yBase);
Thread.Sleep();
}
}
#endregion
}
}
c# 排序算法可视化的更多相关文章
- 【Unity3D自学记录】可视化对照十多种排序算法(C#版)
在这篇文章中.我会向大家展示一些排序算法的可视化过程.我还写了一个工具.大家可对照查看某两种排序算法. 下载源代码 – 75.7 KB 下载演示样例 – 27.1 KB 引言 首先,我觉得是最重要的是 ...
- 基于Qt5的排序算法简单可视化
之前写了几个排序算法,然后看到别人将排序算法的过程可视化出来,所以就想尝试一下,然后就用Qt简单写了个界面,用QImage和QPainter来画图显示,代码比较简单. 我的想法是画图的时候,图像的X轴 ...
- Rxjs入门实践-各种排序算法排序过程的可视化展示
Rxjs入门实践-各种排序算法排序过程的可视化展示 这几天学习下<算法>的排序章节,具体见对排序的总结,想着做点东西,能将各种排序算法的排序过程使用Rxjs通过可视化的方式展示出来,正好练 ...
- 八大排序算法的 Python 实现
转载: 八大排序算法的 Python 实现 本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个 ...
- 排序算法总结(一)插入排序【Insertion Sort】
最近在忙着找工作,以前看的排序算法都忘记了,悲剧啦T T现在来回顾一下吧. 这边推荐一个算法可视化的网站,非常有用.http://visualgo.net/ 一.插入排序的思想(Wikipedia) ...
- [读书笔记]算法(Sedgewick著)·第二章.初级排序算法
本章开始学习排序算法 1.初级排序算法 先从选择排序和插入排序这两个简单的算法开始学习排序算法.选择排序就是依次找到当前数组中最小的元素,将其和第一个元素交换位置,直到整个数组有序. public s ...
- js排序算法汇总
JS家的排序算法 十大经典算法排序总结对比 一张图概括: 主流排序算法概览 名词解释: n: 数据规模k:“桶”的个数In-place: 占用常数内存,不占用额外内存Out-place: 占用额外 ...
- 基本排序算法<二>
归并排序 归并排序,顾名思义,就是通过将两个有序的序列合并为一个大的有序的序列的方式来实现排序.合并排序是一种典型的分治算法:首先将序列分为两部分,然后对每一部分进行循环递归的排序,然后逐个将结果进行 ...
- 排序算法的JS实现
排序算法是基础算法,虽然关键在于算法的思想而不是语言,但还是决定借助算法可视化工具结合自己常用的语言实现一下 1.冒泡排序 基本思路:依次比较两两相邻的两个数,前面数比后面数小,不变.前面数比后面数大 ...
随机推荐
- CSS div内放长英文字母或长数字自动换行 CSS一行排不下自动打断换行
添加css word-wrap:break-word 解释:使用break-word时,是将强制换行. 兼容各版本IE浏览器,兼容谷歌浏览器.
- 深入研究浏览器对HTML解析过程
HTML HTML解析 HTML解析是一个将字节转化为字符,字符解析为标记,标记生成节点,节点构建树的过程. 标记化算法 是词法分析过程,将输入内容解析成多个标记.HTML标记包括起始标记.结束标记. ...
- pycharm内对python文件的模板
#!/usr/bin/env python# -*- coding: utf-8 -*-# @Time : ${DATE} ${TIME}# @Author : Aries# @Site : ${SI ...
- db2模式
模式: 已命名对象的集合,可以对对象进行逻辑分组. 为用户A创建C模式: CREATE SCHEMA <schema-name> [ AUTHORIZATION <schema-ow ...
- 使用 lombok 简化代码
使用前的准备 1.Lombok 是一种 Java™ 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO).它通过注解实现这一目的. <1>添加 ...
- 【记录】iconfont 批量把图标加入购物车的方法
iconfont 是阿里旗下很好用的图标管理网站(https://www.iconfont.cn/),里面有百万个小图标,可以随意下载切换颜色,是很多前端人员的选择. 但是网站没有将图标批量加入购物 ...
- Oracle Linux下使用sqlplus的edit命令
1.使当前会话生效 define_editor=vi SQL> select * from dual; D - X SQL> edit Wrote file afiedt.buf 21 1 ...
- 【串线篇】SpringMvc源码分析
一.DispathcherServlet结构分析 1).所有请求过来DispatcherServlet收到请求, 2).调用doDispatch()方法进行处理 1).getHandler():根据当 ...
- C++ 浅析移位运算
按位左移(<<): 按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零 按位右移(>>): 按二进制形式把所有的数字向右移动对应位移位数,低位移出(舍 ...
- fn:indexOf()详解(jsp中JSTL标签库)
fn:indexOf()函数返回一个字符串中指定子串的位置. 语法 fn:indexOf()函数的语法如下: ${fn:indexOf(<原始字符串>,<子字符串>)} 实例演 ...