前言
刚入门编程的小白第一次发文,还请各路大佬轻点喷/可怜
本文介绍的是简单的排序可视化设计,提供一种控制台输出排序过程的思路,还有待优化的地方,本人也在努力学习中!/加油
如果有什么建议欢迎提出,一起进步!/欢呼
前期准备
库函数:
#include <stdio.h>
#include <stdlib.h> //用于清屏
#include <string.h> //用于数组处理
#include <time.h> //用于随机数生成
Define:
#define maxn 100 //排序最多个数
#define delay 100000 //延迟(微秒)
#define Green "\033[1;32m" //高亮显示
#define None "\033[m" //清楚高亮
全局变量:
int nums[maxn]; //存放打乱后数组
int n; //需要排序的数目
简单功能:
//交换数字
void swap(int num[], int pos1, int pos2)
{
if(pos1 == pos2)return;
int temp = num[pos1];
num[pos1] = num[pos2];
num[pos2] = temp;
}
数组打乱及初始化
打乱数组:
//1 完全随机数组
void compRandomNums()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = 1 + rand() % n;
}
}
//2 打乱递增数组
void randomNums()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = i + 1;
}
for(i = n - 1; i > 0; i--)
{
int p = rand()%i;
swap(nums, p, i);
}
//Fisher–Yates打乱数组
}
//3 递增数组
void numsUp()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = i + 1;
}
}
//4 递减数组
void numsDown()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = n - i;
}
}
//5 几乎有序数组
void numsAlmostOrder()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = i + 1;
}
nums[rand()%n] = 1 + rand() % n;
}
//6 重复数字数组
void numsRepeat()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = (i / 6) * 5 + 1;
}
for(i = n - 1; i > 0; i--)
{
int p = rand() % i;
swap(nums, p, i);
}
}
初始化:
//Initial
srand((unsigned)time(NULL)); //随机数种子
printf("Enter the total number: ");
scanf("%d",&n); //输入数字个数
printf("\nChoose a model:\n\
Completely random(1)\n\
Random(2)\n\
Ascending(3)\n\
Descending(4)\n\
AlmostOrder(5)\n\
Repeating(6)\n");
int mode;
scanf("%d",&mode);getchar();
switch(mode)
{
case 1:compRandomNums();break;
case 2:randomNums();break;
case 3:numsUp();break;
case 4:numsDown();break;
case 5:numsAlmostOrder();break;
case 6:numsRepeat();break;
default:printf("Default.");return 0;
}
//选择数组打乱模式
可视化函数
//可视化函数
void PrintHistogram(int num[], int comPare1, int comPare2)
{
system("cls");
//清屏
char histogram[maxn][maxn];
int i, j;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
histogram[i][j] = ' ';
for(i = 0; i < n; i++)
for(j = n - 1; j >= (n - num[i]); j--)
histogram[j][i] = '*';
//将数组以竖柱状图形式打印
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
if(j == comPare1 || j == comPare2)
printf(Green"%c "None, histogram[i][j]); //高亮被比较的两数
else printf("%c ", histogram[i][j]);
}
printf("\n");
}
//打印柱状图
for(i = 0; i < n; i++)
{
if(i == comPare1 || i == comPare2)
printf(Green"%-2d "None, num[i]);
else
printf("%-2d ", num[i]);
}
printf("\n");
//打印数字
}
函数调用示范
PrintHistogram(nums, -1, -1);
printf("Initial State\n");
getchar(); //等待用户回车
//下面以归并排序为例
//MergeSort
system("cls"); //清屏
printf("MergeSort:\n");
getchar(); //等待用户回车
int numMerge[maxn];
memcpy(numMerge, nums, sizeof(nums));
//复制一个数组用以此次排序
MergeSort(numMerge, 0, n - 1); //排序过程
printf("Sorted.\n");
sleep(2); //等待两秒
//End
system("cls");
printf("- End -\n");
return 0;
排序算法
归并排序:
//MergeSort 归并排序
void MergeSort(int num[], int left, int right)
{
if(left >= right)
return;
int mid = (left + right) / 2;
MergeSort(num, left, mid);
MergeSort(num, mid+1, right);
int i = left, j = mid + 1;
int temp[maxn];
int tempTop = left;
while(i <= mid && j <= right)
{
PrintHistogram(num, i, j);usleep(delay); //每一次比较时等待
if(num[i] < num[j])
{
temp[tempTop++] = num[i++];
}
else
{
temp[tempTop++] = num[j++];
}
}
while(i <= mid) temp[tempTop++] = num[i++];
while(j <= right) temp[tempTop++] = num[j++];
tempTop = left;
while(tempTop <= right)
{
num[tempTop] = temp[tempTop];
tempTop++;
}
PrintHistogram(num,-1,-1); //完成时打印
}
快速排序:
//QuickSort 快速排序(三路快排)
void QuickSort(int num[], int left, int right)
{
if(right - left < 5) //优化:结合插入排序
{
int i, j, temp;
for(i = left + 1; i <= right; i++)
{
temp = num[i];
for(j = i - 1; j >= left; j--)
{
PrintHistogram(num, j, j + 1); usleep(delay); //每一次比较时等待
if(temp < num[j])
{
num[j + 1] = num[j];
num[j] = temp;
}
else break;
}
}
PrintHistogram(num, -1, -1); //完成时打印
return;
}
int pos = left + rand() % (right - left + 1);
swap(num, pos, right);
int lt = left, mt = right - 1;
int i = left, pivot = num[right];
while(i <= mt)
{
PrintHistogram(num, i, right); usleep(delay); //每一次比较时等待
if(num[i] > pivot) swap(num, i, mt--);
else if(num[i] < pivot) swap(num, i++, lt++);
else i++;
}
swap(num, right, mt + 1);
PrintHistogram(num, -1, -1); //完成时打印
QuickSort(num, left, lt - 1);
QuickSort(num, mt + 2, right);
PrintHistogram(num, -1, -1); //完成时打印
}
冒泡排序:
//BubbleSort 冒泡排序(有序优化)
void BubbleSort(int num[])
{
int i, j;
for(i = 0; i < (n - 1); i++)
{
int count = 0;
for(j = 0; j < n - 1 - i; j++)
{
PrintHistogram(num, j, j + 1); usleep(delay); //每一次比较时等待
if(num[j] > num[j + 1])
{
swap(num, j, j + 1);
count++;
}
}
if(!count) break;
}
PrintHistogram(num, -1, -1); //完成时打印
}
选择排序:
//SelectSort 选择排序(最大最小值优化-循环减半)
void SelectSort(int num[])
{
int left = 0, right = n - 1;
while(left < right)
{
int minPos = left, maxPos = right;
int i;
for(i = left; i <= right; i++)
{
PrintHistogram(num, maxPos, minPos); usleep(delay); //每一次比较时等待
if(num[i] < num[minPos]) minPos = i;
if(num[i] > num[maxPos]) maxPos = i;
}
if(maxPos != left) swap(num, minPos, left);
else swap(num, minPos, right);
swap(num, maxPos, right);
left++;
right--;
}
PrintHistogram(num, -1, -1); //完成时打印
}
插入排序:
//InsertSort 插入排序(二分法优化)
void InsertSort(int num[])
{
int i;
for(i = 1; i < n; i++)
{
int left = -1, right = i;
int tmp = num[i];
while(left + 1 < right)
{
int mid = (left + right) / 2;
PrintHistogram(num, i, mid); usleep(delay); //每一次比较时等待
if(num[mid] <= tmp) left = mid;
else right = mid;
}
int j;
for(j = i; j > left + 1; j--)
{
num[j] = num[j - 1];
}
num[j] = tmp;
}
PrintHistogram(num, -1, -1); //完成时打印
}
其他:
暂时就学了这么多,之后有机会再补充。
总结
总代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
//Sorting Visualization
#define maxn 100
#define delay 100000 //Delay(us)
#define Green "\033[1;32m" //HighLight
#define None "\033[m" //ClearHighLight
int nums[maxn];
int n;
//SwapNumbers
void swap(int num[], int pos1, int pos2)
{
if(pos1 == pos2)return;
int temp = num[pos1];
num[pos1] = num[pos2];
num[pos2] = temp;
}
//1 RandomNumbers(Completely Random)
void compRandomNums()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = 1 + rand()%n;
}
}
//2 RandomNumbers
void randomNums()
{
int i, p;
for(i = 0; i < n; i++)
{
nums[i] = i + 1;
}
for(i = n-1; i > 0; i--)
{
p = rand()%i;
swap(nums,p,i);
}
}
//3 numsUp
void numsUp()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = i+1;
}
}
//4 numsDown
void numsDown()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = n-i;
}
}
//5 numsAlmostOrder
void numsAlmostOrder()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = i+1;
}
nums[rand()%n]=1 + rand()%n;
}
//6 numsRepeating
void numsRepeat()
{
int i;
for(i = 0; i < n; i++)
{
nums[i] = (i/6)*5+1;
}
int p;
for(i = n-1; i > 0; i--)
{
p = rand()%i;
swap(nums,p,i);
}
}
//Visualization
void PrintHistogram(int num[], int comPare1, int comPare2)
{
system("cls");
char histogram[maxn][maxn];
int i, j;
for(i=0;i<n;i++)for(j = 0; j < n; j++)histogram[i][j] = ' ';
for(i=0;i<n;i++)for(j = n-1; j >= (n - num[i]); j--)histogram[j][i] = '*';
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(j == comPare1 || j == comPare2) printf(Green"%c "None, histogram[i][j]);
else printf("%c ", histogram[i][j]);
}
printf("\n");
}
for(i=0;i<n;i++)
{
if(i == comPare1 || i == comPare2) printf(Green"%-2d "None, num[i]);
else printf("%-2d ", num[i]);
}
printf("\n");
}
//MergeSort
void MergeSort(int num[], int left, int right)
{
if(left>=right)return;
int mid = (left + right)/2;
MergeSort(num,left,mid);
MergeSort(num,mid+1,right);
int i = left, j = mid+1;
int temp[maxn];
int tempTop = left;
while(i<=mid && j<=right)
{
PrintHistogram(num,i,j);usleep(delay); //wait for each compare
if(num[i]<num[j])
{
temp[tempTop++] = num[i++];
}
else
{
temp[tempTop++] = num[j++];
}
}
while(i<=mid)temp[tempTop++] = num[i++];
while(j<=right)temp[tempTop++] = num[j++];
tempTop = left;
while(tempTop <= right)
{
num[tempTop] = temp[tempTop];
tempTop++;
}
PrintHistogram(num,-1,-1); //complete a part
}
//QuickSort
void QuickSort(int num[], int left, int right)
{
if(right-left<5) //Combine InsertSort
{
int i, j, temp;
for(i = left+1; i <= right; i++)
{
temp = num[i];
for(j = i-1; j >= left; j--)
{
PrintHistogram(num,j,j+1);usleep(delay); //wait for each compare
if(temp < num[j])
{
num[j+1] = num[j];
num[j] = temp;
}
else break;
}
}
PrintHistogram(num,-1,-1); //complete a part
return;
}
int pos = left + rand() % (right-left+1);
swap(num,pos,right);
int lt = left, mt = right - 1;
int i = left, pivot = num[right];
while(i <= mt)
{
PrintHistogram(num,i,right);usleep(delay); //wait for each compare
if(num[i] > pivot) swap(num,i, mt--);
else if(num[i] < pivot) swap(num,i++,lt++);
else i++;
}
swap(num,right,mt+1);
PrintHistogram(num,-1,-1);
QuickSort(num,left,lt - 1);
QuickSort(num,mt + 2,right);
PrintHistogram(num,-1,-1); //complete a part
}
//BubbleSort
void BubbleSort(int num[])
{
int i, j;
for(i = 0; i < (n-1); i++)
{
int count = 0;
for(j = 0; j < n-1-i; j++)
{
PrintHistogram(num,j,j+1);usleep(delay); //wait for each compare
if(num[j]>num[j+1])
{
swap(num,j,j+1);
count++;
}
}
if(!count) break;
}
PrintHistogram(num,-1,-1); //complete
}
//SelectSort
void SelectSort(int num[])
{
int left = 0, right = n-1;
while(left<right)
{
int minPos = left, maxPos = right;
int i;
for(i = left;i<=right;i++)
{
PrintHistogram(num,maxPos,minPos);usleep(delay); //wait for each compare
if(num[i]<num[minPos]) minPos = i;
if(num[i]>num[maxPos]) maxPos = i;
}
if(maxPos != left)swap(num,minPos,left);
else swap(num,minPos,right);
swap(num,maxPos,right);
left++;
right--;
}
PrintHistogram(num,-1,-1); //complete
}
//InsertSort
void InsertSort(int num[])
{
int i;
for(i = 1; i < n; i++)
{
int left = -1, right = i;
int tmp = num[i];
while(left + 1 < right)
{
int mid = (left + right) / 2;
PrintHistogram(num,i,mid);usleep(delay); //wait for each compare
if(num[mid] <= tmp) left = mid;
else right = mid;
}
int j;
for(j = i; j > left + 1; j--)
{
num[j] = num[j - 1];
}
num[j] = tmp;
}
PrintHistogram(num,-1,-1); //complete
}
//Main
int main()
{
//Initial
srand((unsigned)time(NULL));
printf("Enter the total number: ");
scanf("%d",&n);
printf("\nChoose a model:\n\
Completely random(1)\n\
Random(2)\n\
Ascending(3)\n\
Descending(4)\n\
AlmostOrder(5)\n\
Repeating(6)\n");
int choose;
scanf("%d",&choose);getchar();
switch(choose)
{
case 1:compRandomNums();break;
case 2:randomNums();break;
case 3:numsUp();break;
case 4:numsDown();break;
case 5:numsAlmostOrder();break;
case 6:numsRepeat();break;
default:printf("Default.");return 0;
}
PrintHistogram(nums,-1,-1);
printf("Initial State\n");
getchar();
//MergeSort
system("cls");
printf("MergeSort:\n");
getchar();
int numMerge[maxn];
memcpy(numMerge,nums,sizeof(nums));
MergeSort(numMerge,0,n-1);
printf("Sorted.\n");
sleep(2);
//QuickSort
system("cls");
printf("QuickSort:\n");
getchar();
int numQuick[maxn];
memcpy(numQuick,nums,sizeof(nums));
QuickSort(numQuick,0,n-1);
printf("Sorted.\n");
sleep(2);
//BubbleSort
system("cls");
printf("BubbleSort:\n");
getchar();
int numBubble[maxn];
memcpy(numBubble,nums,sizeof(nums));
BubbleSort(numBubble);
printf("Sorted.\n");
sleep(2);
//SelectSort
system("cls");
printf("SelectSort:\n");
getchar();
int numSelect[maxn];
memcpy(numSelect,nums,sizeof(nums));
SelectSort(numSelect);
printf("Sorted.\n");
sleep(2);
//InsertSort
system("cls");
printf("InsertSort:\n");
getchar();
int numInsert[maxn];
memcpy(numInsert,nums,sizeof(nums));
InsertSort(numInsert);
printf("Sorted.\n");
sleep(2);
//End
system("cls");
printf("- End -\n");
return 0;
}
最后,感谢各位读者阅读啦!