温故而知新 -> 数据结构 ->排序 ->程序实现2_利用C++

温故而知新 -> 数据结构 ->排序 ->程序实现2_利用C++

本篇博客是基于 温故而知新 -> 数据结构 ->排序 中部分 排序 的理论知识进行程序实现!

其中实现了 交换排序中的三种快速排序递归与非递归的归并排序非比较排序等!并附带了相关实例以及对应的运行结果!

由于上述的程序实现中使用了顺序表队列,即还需实现顺序表与队列这两个内容,如此会导致程序代码量大幅增多。而在程序中,为了清晰展示各部分的实现代码,所以加上各自的头文件共有 5 个文件,即 Queue.hSeqList.hqueue.cppseqList.cppmain.cpp

其中 Queue.hqueue.cpp 的内容与 温故而知新->数据结构->队列->程序实现2_利用类 博客中的 queue.hmain.cpp 对应且相同,但为方便本次程序的运行,需将上述博客的 main.cpp 中的 test()main() 两个函数进行删除或注释;
SeqList.hseqList.cpp 的内容与 温故而知新->数据结构->顺序表->程序实现2_利用类 博客中的 seqList.hmain.cpp 对应且相同,也为方便本次程序的运行,需将上述博客的 main.cpp 中的 test()main() 两个函数进行删除或注释。

在下述内容中将附上本次程序的 main.cpp 文件内容,其他文件内容可根据上述指引自行查看!

注意:下述代码多多少少有点冗余,且未考虑性能最优,读者有兴趣可进一步精简!

具体内容如下:

(1)main.cpp

#include"Queue.h"
#include"SeqList.h"
#include<string>

void swap(int *arr, int a, int b)
{
	int t = arr[a];
	arr[a] = arr[b];
	arr[b] = t;
}

// 交换排序 之 冒泡排序  从小到大
void BubbleSort(int *arr, int n)
{
	int m = n;
	while (m > 1)
	{
		int flag = 0;
		for (int i = 1; i < n; i++)
		{
			if (arr[i - 1] > arr[i])
			{
				swap(arr, i - 1, i);
				flag = 1;
			}
		}
		if (!flag)
			break;
		m--;
	}
}

//快速排序中设定基准值
int getMid(int *arr, int begin, int end)
{
	int mid = begin + (end - begin) / 2;
	if (arr[begin] > arr[end])
	{
		if (arr[mid] <= arr[end])//arr[begin] > arr[end] > arr[mid]
			return end;
		else if (arr[begin] <= arr[mid])// arr[mid] > arr[begin] > arr[end] 
			return begin;
		else//arr[begin] > arr[mid] > arr[end]
			return mid;
	}
	else //arr[begin] <= arr[end]
	{
		if (arr[mid] <= arr[begin]) // arr[mid] < arr[begin] < arr[end]
			return begin;
		else if (arr[mid] >= arr[end])//  arr[begin] < arr[end] < arr[mid] 
			return end;
		else// arr[begin] <= arr[mid] <= arr[end] 
			return mid;
	}
}
// 交换排序 之 快速排序 之 hoare法
// 返回划分后基准值所在的位置
int partion(int *arr, int begin, int end)
{
	int mid = getMid(arr, begin, end);
	//将基准值放到起始位置
	swap(arr, begin, mid);
	int key = arr[begin];
	int start = begin;
	while (begin < end)
	{
		//从后向前先找小于基准值的位置
		while (begin < end && arr[end] >= key)
			--end;
		//从前往后找大于基准值的位置
		while (begin < end && arr[begin] <= key)
			++begin;
		swap(arr, begin, end);
	}
	//交换基准值与相遇位置的数据
	swap(arr, start, begin);
	return begin;
}
// 交换排序 之 快速排序 之 挖坑法
int partion2(int *arr, int begin, int end)
{
	int mid = getMid(arr, begin, end);
	swap(arr, begin, mid);
	// 第一个值作为基准值,第一个位置为初始的坑的位置
	int key = arr[begin];
	while (begin < end)
	{
		while (begin < end && arr[end] >= key)
			--end;
		arr[begin] = arr[end];
		while (begin < end && arr[begin] <= key)
			++begin;
		arr[end] = arr[begin];
	}
	arr[begin] = key;
	return begin;
}
// 交换排序 之 快速排序 之 前后指针法
int partion3(int *arr, int begin, int end)
{
	int prev = begin;
	int cur = begin + 1;
	int key = arr[begin];
	while (cur <= end)
	{
		if (arr[cur] < key && ++prev != cur)//小于基准值且不连续时进行交换
		{
			swap(arr, prev, cur);
		}
		++cur;
	}
	swap(arr, begin, prev);
	return prev;
}
// 交换排序 之 递归快排
void quickSort(int *arr, int begin, int end)//hoare的实现
{
	if (begin >= end)
		return;
	int div = partion3(arr, begin, end);
	//对左右两部分进行快速排序
	quickSort(arr, begin, div - 1);
	quickSort(arr, div + 1, end);
}
// 非递归快排 用顺序表
void quickSortNor(int *arr, int n)
{
	//创建顺序表
	SeqList sq;
	sq.PushBack(n - 1);
	sq.PushBack(0);
	while (!sq.Empty())
	{
		int left = sq.ListBack();
		sq.PopBack();
		int right = sq.ListBack();
		sq.PopBack();

		int div = partion(arr, left, right);

		if (left < div - 1)
		{
			sq.PushBack(div - 1);
			sq.PushBack(left);
		}
		if (div + 1 < right)
		{
			sq.PushBack(right);
			sq.PushBack(div + 1);
		}
	}
}
// 非递归快排 用队列  先进先出
void quickSortNor2(int *arr, int n)
{
	Queue q;
	q.QueuePush(0);
	q.QueuePush(n - 1);

	while (!q.QueueEmpty())
	{
		int left = q.QueueFront();
		q.QueuePop();
		int right = q.QueueFront();
		q.QueuePop();

		int div = partion(arr, left, right);
		if (left < div - 1)
		{
			q.QueuePush(left);
			q.QueuePush(div - 1);
		}
		if (div + 1 < right)
		{
			q.QueuePush(div + 1);
			q.QueuePush(right);
		}
	}
}

//归并排序
//相邻子序列合并
void merge(int *arr, int begin, int mid, int end, int *tmp)
{
	int begin1 = begin;
	int end1 = mid;
	int begin2 = mid + 1;
	int end2 = end;

	//辅助空间的起始位置
	int idx = begin;

	//合并有序序列
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (arr[begin1] <= arr[begin2])
			tmp[idx++] = arr[begin1++];
		else
			tmp[idx++] = arr[begin2++];
	}

	//判断是否有未合并的元素,下面语句实现的功能是将原数组中的[begin,end]中的数据拷贝到
	//合并后之后的位置上了,防止一些数据没有合并到
	if (begin1 <= end1)
		memcpy(tmp + idx, arr + begin1, sizeof(int)*(end1 - begin1 + 1));
	if (begin2 <= end2)
		memcpy(tmp + idx, arr + begin2, sizeof(int)*(end2 - begin2 + 1));

	//合并之后的序列拷贝到原始数据的对应区间
	memcpy(arr + begin, tmp + begin, sizeof(int)*(end - begin + 1));
}
void _mergeSort(int *arr, int begin, int end, int *tmp)
{
	if (begin >= end)
		return;
	int mid = begin + (end - begin) / 2;
	_mergeSort(arr, begin, mid, tmp);
	_mergeSort(arr, mid + 1, end, tmp);
	merge(arr, begin, mid, end, tmp);
}
void mergeSort(int *arr, int n)//递归
{
	int *tmp = (int*)malloc(sizeof(int)*n);
	_mergeSort(arr, 0, n - 1, tmp);
	free(tmp);
}

//归并非递归
void mergeSortNor(int *arr, int n)
{
	int *tmp = (int*)malloc(sizeof(int)*n);
	int step = 1;
	while (step < n)
	{
		for (int idx = 0; idx < n; idx += 2 * step)
		{
			int begin = idx;
			int mid = idx + step - 1;
			if (mid >= n - 1)//判断是否存在第二个子序列,不存在直接跳过
				continue;
			int end = idx + 2 * step - 1;
			if (end >= n)
				end = n - 1;
			merge(arr, begin, mid, end, tmp);
		}
		step *= 2;
	}
	//free(tmp);
}

//非比较排序
void countSort(int *arr, int n)
{
	int max, min;
	min = max = arr[0];
	for (int i = 1; i < n; i++)
	{
		if (min > arr[i])
			min = arr[i];
		if (max < arr[i])
			max = arr[i];
	}
	int range = max - min + 1;
	int *tmp = (int*)calloc(range, sizeof(int));
	//计数  计算arr中相同数字的个数
	for (int i = 0; i < n; i++)
	{
		tmp[arr[i] - min]++;
	}
	//遍历计数数组tmp,进行排序
	int idx = 0;
	for (int i = 0; i < range; i++)
	{
		while (tmp[i]--)
		{
			arr[idx++] = i + min;
		}
	}
}

//打印数组
void printArr(int *arr, int n)
{
	for (int i = 0; i < n; i++)
		cout << arr[i] << " ";
	cout << endl;
}

void test()
{
	int arr1[] = { 6, 3, 1, 8, 7, 2, 4 };
	int n = sizeof(arr1) / sizeof(arr1[0]);
	int *arr2 = (int*)malloc(sizeof(int)*n);
	memcpy(arr2, arr1, sizeof(arr1));
	cout << "排序前内容:"<< endl;
	printArr(arr1, n); cout << endl;

	cout << "冒泡排序后内容:" << endl;
	BubbleSort(arr2, n);
	printArr(arr2, n); cout << endl;
	memcpy(arr2, arr1, sizeof(arr1));

	cout << "递归快排后内容:" << endl;
	quickSort(arr2, 0, n - 1);
	printArr(arr2, n); cout << endl;
	memcpy(arr2, arr1, sizeof(arr1));

	cout << "非递归快排(利用顺序表)后内容:" << endl;
	quickSortNor(arr2, n);
	printArr(arr2, n); cout << endl;
	memcpy(arr2, arr1, sizeof(arr1));

	cout << "非递归快排(利用队列 )后内容:" << endl;
	quickSortNor(arr2, n);
	printArr(arr2, n); cout << endl;
	memcpy(arr2, arr1, sizeof(arr1));

	cout << "递归归并后内容:" << endl;
	mergeSort(arr2, n);
	printArr(arr2, n); cout << endl;
	memcpy(arr2, arr1, sizeof(arr1));

	cout << "非递归归并后内容:" << endl;
	mergeSortNor(arr2, n);
	printArr(arr2, n); cout << endl;
	memcpy(arr2, arr1, sizeof(arr1));

	cout << "非比较排序后内容:" << endl;
	countSort(arr2, n);
	printArr(arr2, n); cout << endl;
	memcpy(arr2, arr1, sizeof(arr1));
}

int main()
{
	test();
	system("pause");
	return 0;
}

(2)运行结果
温故而知新 -> 数据结构 ->排序 ->程序实现2_利用C++
侵权删~

上一篇:解决maven项目打包时报错:Error injecting constructor


下一篇:ill-intentions