前言
最近看劉老師視頻重新學習算法,記錄下學習過程。
選擇排序算法
選擇排序算法是交換算法的一種。
每一次都從待排序的數據組合裏找到最小(或最大)的一個元素放到已排好序的序列中。
選擇排序算法核心代碼:
public void selectSort(int [] arr){
for (int i = 0; i < arr.length; i++) {
int minIndex = i;
int j;
// 找出最小值的元素下標
for (j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
// 保存當前找到的最小值的元素下標
minIndex = j;
}
}
// 將目前找到的最小值放到有序隊列中
int tmp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = tmp;
}
}
可視化
用四種顏色動態展示排序過程。(在此展示的是由小到大的排序)
灰色:待排序元素
紅色:已有序元素
藍色:正在遍歷的元素
紫色:目前選出的最小元素
數據層:SelectionSortData.java
package Demo;
public class SelectionSortData {
private int[] number;
public int orderedIndex = -1; // 在[0,orderedIndex]內是有序的
public int currentCompareIndex = -1; // 當前正在比較的元素下標
public int currentMinIndex = -1; // 當前找到的最小值的元素下標
public SelectionSortData(int randomBound,int N){
if(randomBound <=0 || N<=0)
throw new IllegalArgumentException("SceneHeight or N must larger than 0 ");
number = new int[N];
// 生成隨機數組
for(int i=0;i<N;i++){
number[i] = (int)(Math.random()*randomBound) + 1;
}
}
// 獲得數組指定下標的元素
public int getNumber(int i){
if ( i < 0 || i >= number.length )
throw new IllegalArgumentException("out of index ");
return number[i];
}
// 獲得數組長度
public int getN() {
return number.length;
}
// 元素交換
public void swap(int i,int j){
int temp = number[i];
number[i] = number[j];
number[j] = temp;
}
}
視圖層:SortFrame.java
package Demo;
import javax.swing.*;
import java.awt.*;
public class SortFrame extends JFrame {
private int canvasWidth;
private int canvasHeight;
public SortFrame(String title,int canvasWidth,int canvasHeight){
super(title);
// 畫布
SortCanvas sortCanvas = new SortCanvas();
setContentPane(sortCanvas);
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
setSize(canvasWidth,canvasHeight); // 設置窗口大小
setResizable(true); // 窗口可進行縮放
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack(); // 窗口大小自適應
setVisible(true); // 窗口可見
}
// 數據內容渲染
private SelectionSortData data;
public void render(SelectionSortData data){
this.data = data;
repaint();
}
private class SortCanvas extends JPanel{
public SortCanvas(){
super(true); // 允許雙緩存
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D graphics2D = (Graphics2D)g;
// 抗鋸齒
RenderingHints renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
graphics2D.addRenderingHints(renderingHints);
// 具體繪製
int w = canvasWidth / data.getN(); // 矩形寬度
for(int i=0;i<data.getN();i++){
if(i < data.orderedIndex) // 已有序的數組元素
SortVisHelper.setColor(graphics2D,Color.RED);
else // 無序的數組元素
SortVisHelper.setColor(graphics2D,Color.GRAY);
if(i == data.currentCompareIndex) // 正在進行比較的元素
SortVisHelper.setColor(graphics2D,Color.BLUE);
if(i == data.currentMinIndex) // 當前找到的最小值的元素
SortVisHelper.setColor(graphics2D,Color.MAGENTA);
// 畫矩形
SortVisHelper.filledRectangle(graphics2D,i*w,canvasHeight-data.getNumber(i),w-1,data.getNumber(i));
}
}
@Override
public Dimension getPreferredSize(){
return new Dimension(canvasWidth,canvasHeight);
}
}
}
控制層:SortVisualizer.java
package Demo;
import java.awt.*;
public class SortVisualizer {
private SelectionSortData data; // 數據
private SortFrame sortFrame; // 視圖
publicSortVisualizer(int sceneWidth,int sceneHeight,int N){
// 初始化數據
data = new SelectionSortData(sceneHeight,N);
// 初始化視圖
sortFrame = new SortFrame("選擇排序",sceneWidth,sceneHeight);
EventQueue.invokeLater(()->{
new Thread(()->{
run();
}).start();
});
}
// 動畫邏輯
private void run(){
// 更新繪製
setData(0,-1,-1);
// 選擇排序算法
for(int i = 0;i < data.getN();i++){
int minIndex = i;
setData(i,-1,minIndex);
for(int j = i+1;j < data.getN();j++){
setData(i,j,minIndex);
if(data.getNumber(j) < data.getNumber(minIndex))
minIndex = j;
setData(i,j,minIndex);
}
data.swap(i,minIndex);
setData(i+1,-1,-1);
}
setData(data.getN(),-1,-1);
}
// 實時更新元素狀態
public void setData(int orderedIndex,int currentCompareIndex,int currentMinIndex){
data.orderedIndex = orderedIndex;
data.currentCompareIndex = currentCompareIndex;
data.currentMinIndex = currentMinIndex;
sortFrame.render(data);
SortVisHelper.pause(50);
}
}
畫圖輔助類:SortVisHelper.java
package Demo;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
public class SortVisHelper {
// 不允許外部類實例化
private SortVisHelper(){}
// 設置顏色
public static void setColor(Graphics2D g,Color color){
g.setColor(color);
}
// 空心矩形
public static void storkeRectangle(Graphics2D g,int x,int y,int w,int h){
Rectangle2D rectangle = new Rectangle2D.Double(x,y,w,h);
g.draw(rectangle);
}
// 實心矩形
public static void filledRectangle(Graphics2D g,int x,int y,int w,int h){
Rectangle2D rectangle = new Rectangle2D.Double(x,y,w,h);
g.fill(rectangle);
}
// 暫停
public static void pause(int time){
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}