数据结构课设——排序综合(C语言)

本文详细介绍了C语言实现的六种排序算法,包括插入排序、希尔排序、冒泡排序、快速排序、选择排序和归并排序,并提供了每种排序方法的步骤、时间复杂度和空间复杂度。此外,程序还统计了每种排序方法的性能,通过比较运行时间来找出最快的方法。
摘要由CSDN通过智能技术生成

数据结构课设——排序综合(C语言)

题目

利用随机函数产生N个随机整数(20000以上),对这些数进行多种方法进行排序。

要求:

  1. 至少采用四种方法实现上述问题求解(提示,可采用的方法有插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序)。并把排序后的结果保存在不同的文件中。
  2. 统计每一种排序方法的性能(以上机运行程序所花费的时间为准进行对比,),找出其中两种较快的方法。

本程序中用到了6种排序方法。

随机数的生成

srand((unsigned)time(NULL));

srand用来初始化随机种子,会提供一个种子,这个种子会对应一个随机数。
为了防止随机数每次重复,这里使用系统时间来作为随机种子。

1.插入排序

步骤

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取下一个元素temp,从已排序的元素序列从后往前遍历
  3. 如果该元素大于temp,则将该元素移到下一位
  4. 重复步骤3,直到找到已排序元素中小于等于temp的元素
  5. temp插入到元素的后面,如果已排序的元素都大于temp,则将temp插入到下标为0的位置
  6. 重复步骤2~5

动图演示如下:
selectionSort.gif

void insertSort()
{
    for (int i = 1; i < CAPACITY; i++)
	{
		int temp = array[i];
		int j = i - 1;
		while (j >= 0)
		{
			//说明前面已经有序了
			if (array[j] <= temp)
			{
				break;
			}
			//移动j的值到j+1
			array[j + 1] = array[j];
			j--;
		}
		array[j + 1] = temp;
	}
}
  • 时间复杂度:最坏情况:O( N 2 N^2 N2),最好情况 O(N)
  • 空间复杂度:O(1)
  • 稳定性:稳定

2.希尔排序

希尔排序又称缩小增量法

步骤

  1. 先定义一下分组个数gap
  2. 把整个数组分成gap个组,每个组里有CAPACITY/gap个元素
  3. 把每个小组分别用插入方式排序
  4. 逐渐缩小这个gap,直到gap=1时,全部排序完成

shell.gif
image.png

void shellSort()
{
	int gap = CAPACITY / 2;
	while (gap > 0)
	{
		shell( gap);
		gap /= 2;
	}
}
//核心代码
void shell( int gap)
{

	for (int i = gap; i < CAPACITY; i++) 
	{
		int temp = array[i];
		int j = i - gap;
		while (j >= 0)
		{
			if (array[j] <= temp) 
			{
				break;
			}
			array[j + gap] = array[j];
			j -= gap;
		}
		array[j + gap] = temp;
	}
}
  • 时间复杂度:O( N 1.25 N^{1.25} N1.25) ~ O( N 1.5 N^{1.5} N1.5)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

3.冒泡排序

左边大于右边交换一趟排下来最大的在右边
bubble.gif

void bubbleSort()
{
	for (int i = 0; i < CAPACITY - 1; i++) {
		int set = 0;
		for (int j = 0; j < CAPACITY - 1 - i; j++) 
		{
			if (array[j] > array[j + 1]) 
			{
				swap(j, j + 1);
				set = 1;
			}
			
		}
		if (set==0)
		{
			break;
		}
		
	}
}
void swap(int left, int right)
{
	int temp = array[left];
	array[left] = array[right];
	array[right] = temp;
}
  • 时间复杂度:O( N 2 N^2 N2)
  • 空间复杂度:O(1)
  • 稳定性:稳定

4.快速排序

挖坑法找基准

  1. left下标的值当做默认的基准值,这时left的位置就空出来了
  2. right向左移动,找到比基准值小的值,放到left的位置
  3. left向右移动,找到比基准值大的值,放到right的位置
  4. leftright相遇时,把之前记录的基准值放在相遇的下标
  5. 返回相遇点下标,这就是基准的下标

quic.gif

//快速排序
void quickSort()
{
	const int N = 1e2;
    start = clock();

	quickSortProcess(0, CAPACITY - 1);

	end = clock();
	printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N);

}
//核心代码
void quickSortProcess(int left, int right)
{
	if (left>=right)
	{
		return;
	}
	//找基准
	int pivot= partitionHole(left, right);
	quickSortProcess(left, pivot);
	quickSortProcess( pivot+1,right);

}

int partitionHole(int left, int right)
{
	int pivotValue = array[left];
	
	while (left < right) 
	{
		while (right > left && array[right] >= pivotValue) 
		{
			right--;
		}
		array[left] = array[right];
		while (left < right && array[left] <= pivotValue) 
		{
			left++;
		}
		array[right] = array[left];
	}
	array[left] = pivotValue;
	return left;
}
  • 时间复杂度:O(N* l o g N logN logN)

  • 空间复杂度:O( l o g N logN logN)

  • 稳定性:不稳定

5.选择排序

步骤

  1. 定义数组边界,left=0,right=CAPACITY-1
  2. 定义i用来遍历
  3. 定义最小值下标minIndex=left,maxIndex=left
  4. i遍历的过程中,找到比最小值小的元素更新minIndex,找到比最大值大的元素更新maxIndex
  5. 一轮遍历完成后,leftminIndex交换,right与maxIndex交换
  6. 循环终止条件是left<rigth

select.gif

//选择排序
void selectSort()
{
	int left = 0;
	int right = CAPACITY - 1;
	while (left < right) 
	{
		int minIndex = left;
		int maxIndex = left;
		//找最大值和最小值
		for (int i = left + 1; i <= right; i++) 
		{
			if (array[i] < array[minIndex]) 
			{
				minIndex = i;
			}
			if (array[i] > array[maxIndex]) 
			{
				maxIndex = i;
			}
		}
		if (left != minIndex) 
		{
			swap(left, minIndex);
		}
		if (left == maxIndex) 
		{
			minIndex = maxIndex;
		}
		if (right != maxIndex) 
		{
			swap(right, maxIndex);
		}
		left++;
		right--;
	}
}
  • 时间复杂度:O( N 2 N^2 N2)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

6.归并排序

步骤

  1. 把大数组分解成若干个小数组

  2. 把小数组做归并操作,并在归并的过程中完成排序

    1. 在归并的过程中,需要用到一个临时数组来存储排序好的数据,那么这个数组的容量为 right-left+1
    2. 确定每个小数组的开始与结束下标
    3. 合并两个数组,合并的方法可以参考合并有序数组的过程
      1. 两个数组都不为空的情况下,比当前位置元素的大小,小的那一个直接加入到临时数组里
      2. 如果两个数组的元素个数不一样多,那么就要处理有剩余元素的数组,直接把剩余元素追加到临时数组里
  3. 把临时数组中排序好的元素,覆盖到原数组对应的下标

image.png

//归并排序
void mergeSort()
{
    mergeSortProcessor( 0, CAPACITY - 1);
}
void mergeSortProcessor(int left, int right)
{
    //1、终止条件
    if (left >= right) {
        return;
    }
    //2、找中间下标
    int mid = (left + right) / 2;
    //3、分解左右区段
    mergeSortProcessor( left, mid);
    mergeSortProcessor( mid + 1, right);
    //4、合并
    marge( left, mid, right);
}
void marge(int left, int mid, int right)
{
    //1、创建临时数组
    //int n = (right - left + 1);

    int *temp=(int*)malloc((right - left + 1)*sizeof(int));
    int index = 0;
    //2、确定每个小数组的下标
    int start1 = left;
    int end1 = mid;
    int start2 = mid + 1;
    int end2 = right;
    //3、合并
    while (start1 <= end1 && start2 <= end2) {
        if (array[start1] < array[start2]) {
            temp[index++] = array[start1++];
        }
        else {
            temp[index++] = array[start2++];
        }
    }
    //剩余元素添加到temp中
    while (start1 <= end1) {
        temp[index++] = array[start1++];
    }
    while (start2 <= end2) {
        temp[index++] = array[start2++];
    }
    //4、temp写到原数组中
    for (int i = 0; i < index; i++) {
        array[i + left] = temp[i];
    }
    free(temp);
    temp = NULL;
}
  • 时间复杂度:O(N* l o g N logN logN)
  • 空间复杂度:O(N)
  • 稳定性:稳定

完整代码

sort.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define CAPACITY 20000
int array[CAPACITY];
clock_t start, end;


void initArray();
void save(char* name1);
void dispaly();
void swap(int i, int minIndex);
//插入排序
void insertSort();
//希尔排序
void shellSort();
void shell(int gap);
//冒泡排序
void bubbleSort();
//快速排序
void quickSort();
void quickSortProcess(int left, int right);
int partitionHole(int left, int right);

//选择排序
void selectSort();

//归并排序
void mergeSort();
void mergeSortProcessor(int left, int right);
void marge(int left, int mid, int right);

sort.c

#include"sort.h"
void initArray()
{
	srand((unsigned)time(NULL));
	for (int i = 0; i < CAPACITY; i++)
	{
		array[i] = rand();
	}

}

void save(char* name1)
{
	FILE* fp;

	char* name2 = ".txt";
	char* name = (char*)malloc(strlen(name1) + strlen(name2));
	strcpy(name, name1);
	strcat(name, name2);
	fp = fopen(name, "w");
	int count = 0;
	for (int i = 0; i < CAPACITY; i++)
	{
		fprintf(fp, "%6d", array[i]);
		count++;
		if (count%100==0)
		{
			fprintf(fp, "\n");
		}
	}
	fclose(fp);
}

void dispaly()
{
	int count = 0;

	for (int i = 0; i < CAPACITY; i++)
	{
		printf("%6d", array[i]);
		count++;
		if (count % 20 == 0)
		{
			printf("\n");
		}

	}
	printf("\n");

}

//插入排序
void insertSort()
{
	const int N = 1e2;
	start = clock();
	for (int i = 1; i < CAPACITY; i++)
	{
		int temp = array[i];
		int j = i - 1;
		while (j >= 0)
		{
			//说明前面已经有序了
			if (array[j] <= temp)
			{
				break;
			}
			//移动j的值到j+1
			array[j + 1] = array[j];
			j--;
		}
		array[j + 1] = temp;
	}
	end = clock();
	printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N);
}


//希尔排序
void shellSort()
{
	const int N = 1e2;
	start = clock();
	int gap = CAPACITY / 2;
	while (gap > 0)
	{
		shell( gap);
		gap /= 2;
	}
	end = clock();
	printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N);

}

void shell( int gap)
{

	for (int i = gap; i < CAPACITY; i++) 
	{
		int temp = array[i];
		int j = i - gap;
		while (j >= 0)
		{
			if (array[j] <= temp) 
			{
				break;
			}
			array[j + gap] = array[j];
			j -= gap;
		}
		array[j + gap] = temp;
	}
}

void swap(int left, int right)
{
	int temp = array[left];
	array[left] = array[right];
	array[right] = temp;
}

//冒泡排序
void bubbleSort()
{
	const int N = 1e2;
	start = clock();
	for (int i = 0; i < CAPACITY - 1; i++) {
		int set = 0;
		for (int j = 0; j < CAPACITY - 1 - i; j++) 
		{
			if (array[j] > array[j + 1]) 
			{
				swap(j, j + 1);
				set = 1;
			}
			
		}
		if (set==0)
		{
			break;
		}
		
	}
	end = clock();
	printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N);

}

//快速排序
void quickSort()
{
	const int N = 1e2;
    start = clock();

	quickSortProcess(0, CAPACITY - 1);

	end = clock();
	printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N);

}
//核心代码
void quickSortProcess(int left, int right)
{
	if (left>=right)
	{
		return;
	}
	//找基准
	int pivot= partitionHole(left, right);
	quickSortProcess(left, pivot);
	quickSortProcess( pivot+1,right);

}

int partitionHole(int left, int right)
{
	int pivotValue = array[left];
	
	while (left < right) 
	{
		while (right > left && array[right] >= pivotValue) 
		{
			right--;
		}
		array[left] = array[right];
		while (left < right && array[left] <= pivotValue) 
		{
			left++;
		}
		array[right] = array[left];
	}
	array[left] = pivotValue;
	return left;
}



//选择排序
void selectSort()
{
	const int N = 1e2;
    start = clock();
	int left = 0;
	int right = CAPACITY - 1;
	while (left < right) 
	{
		int minIndex = left;
		int maxIndex = left;
		//找最大值和最小值
		for (int i = left + 1; i <= right; i++) 
		{
			if (array[i] < array[minIndex]) 
			{
				minIndex = i;
			}
			if (array[i] > array[maxIndex]) 
			{
				maxIndex = i;
			}
		}
		if (left != minIndex) 
		{
			swap(left, minIndex);
		}
		if (left == maxIndex) 
		{
			minIndex = maxIndex;
		}
		if (right != maxIndex) 
		{
			swap(right, maxIndex);
		}
		left++;
		right--;
	}
	end = clock();
    printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N);

}


//归并排序
void mergeSort()
{
	
    const int N = 1e2;
	start = clock();

	mergeSortProcessor( 0, CAPACITY - 1);
	end = clock();
    printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N);

}
void mergeSortProcessor(int left, int right)
{
	//1、终止条件
	if (left >= right) {
		return;
	}
	//2、找中间下标
	int mid = (left + right) / 2;
	//3、分解左右区段
	mergeSortProcessor( left, mid);
	mergeSortProcessor( mid + 1, right);
	//4、合并
	marge( left, mid, right);
}
void marge(int left, int mid, int right)
{
	//1、创建临时数组
	//int n = (right - left + 1);
	
	int *temp=(int*)malloc((right - left + 1)*sizeof(int));
	int index = 0;
	//2、确定每个小数组的下标
	int start1 = left;
	int end1 = mid;
	int start2 = mid + 1;
	int end2 = right;
	//3、合并
	while (start1 <= end1 && start2 <= end2) {
		if (array[start1] < array[start2]) {
			temp[index++] = array[start1++];
		}
		else {
			temp[index++] = array[start2++];
		}
	}
	//剩余元素添加到temp中
	while (start1 <= end1) {
		temp[index++] = array[start1++];
	}
	while (start2 <= end2) {
		temp[index++] = array[start2++];
	}
	//4、temp写到原数组中
	for (int i = 0; i < index; i++) {
		array[i + left] = temp[i];
	}
	free(temp);
	temp = NULL;
}

main.c

#include"sort.h"
void menu()
{
	printf("+===================================+\n");
	printf("+        欢迎使用综合排序系统       +\n");
	printf("+            1.插入排序             +\n");
	printf("+            2.希尔排序             +\n");
	printf("+            3.冒泡排序             +\n");
	printf("+            4.快速排序             +\n");
	printf("+            5.选择排序             +\n");
	printf("+            6.归并排序             +\n");
	printf("+            0.退出程序             +\n");
	printf("+===================================+\n");

}
void setting()
{
	system("color 0b");
	
}
int main()
{
	setting();
	while (1)
	{
		int select;
		//生成随机数组
		initArray();
		//dispaly();
		menu();
		printf("请选择需要进行的操作:");
		scanf("%d", &select);
		switch (select)
		{
		case 1:
			insertSort();
			save("插入排序");
			system("pause");
			system("cls");
			break;
		case 2:
			shellSort();
			save("希尔排序");
			system("pause");
			system("cls");
			break;
		case 3:
			bubbleSort();
			save("冒泡排序");
			system("pause");
			system("cls");
			break;
		case 4:
			quickSort();
			save("快速排序");
			//dispaly();
			system("pause");
			system("cls");
			break;
		case 5:
			selectSort();
			save("选择排序");
			system("pause");
			system("cls");
			break;

		case 6:
			mergeSort();
			save("归并排序");
			system("pause");
			system("cls");
			break;
		case 0:
			printf("拜拜,欢迎下次使用.....\n");
			return 0;
			break;
		default:
			printf("选择无效,请重新选择!!!\n");
			system("pause");
			system("cls");
			break;
		}
	}
}
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小 王

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

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

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

打赏作者

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

抵扣说明:

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

余额充值