C语言简单排序可视化设计


前言

        刚入门编程的小白第一次发文,还请各路大佬轻点喷/可怜

        本文介绍的是简单的排序可视化设计,提供一种控制台输出排序过程的思路,还有待优化的地方,本人也在努力学习中!/加油

        如果有什么建议欢迎提出,一起进步!/欢呼


前期准备

库函数:

#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;
}

最后,感谢各位读者阅读啦!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YoruAi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值