模板数组类-练习排序

本文存储的是自己实现的一个模板数组类(为了练习排序)

模板

//排序数组  存在MySort_vector.hpp
template<typename Elemtype>
class MyArray {
private:
	Elemtype* arr;
	int size;
public:
	MyArray(int getSize = 0) :size(getSize) {}
	void Swap(Elemtype* a, Elemtype* b);
	void Array_init();
	void show();
	void Bubble_sort();
	void Select_sort();
	void Insert_sort();
	void Shell_sort();
	void Quick_sort(int begin, int end);
	void Radix_sort();
	void Merge_sort(int left, int right);//核心递归函数
	void Merge_in_arr(int left, int mid, int right);//合并函数
	Elemtype Binary_search(Elemtype data);
};

template<typename Elemtype>
void MyArray<Elemtype>::Swap(Elemtype* a, Elemtype* b)
{
	Elemtype temp = *a;
	*a = *b;
	*b = temp;
}

template<typename Elemtype>
void MyArray<Elemtype>::Array_init()
{
	arr = new Elemtype[size]();
	for (int i = 0; i < size; ++i)
	{
		std::cin >> arr[i];
	}
}

template<typename Elemtype>
void MyArray<Elemtype>::show()
{
	for (int i = 0; i < size; ++i)
	{
		std::cout << arr[i] << " ";
	}
	std::cout << std::endl;
}


//冒泡排序
template<typename Elemtype>
void MyArray<Elemtype>::Bubble_sort()
{
	if (size <= 0)
	{
		return;
	}
	int length = size;
	int flag = 0;   //作为是否交换的标记
	while (length--)
	{
		for (int i = 0; i < length; i++)
		{
			if (arr[i] > arr[i + 1])
			{
				Swap(arr + i, arr + i + 1);
				flag = 1;
			}
		}
		if (0 == flag)  // //提高效率,如果中途就排好了,就提前退出
			return;
	}
}

//选择排序
template<typename Elemtype>
void MyArray<Elemtype>::Select_sort()
{
	if (size <= 0)
		return;
	int begin = 0, end = size - 1;
	while (begin < end)
	{
		int max = begin, min = end;
		for (int i = begin; i <= end; ++i)
		{
			if (arr[i] > arr[max])  max = i;
			if (arr[i] < arr[min])  min = i;
		}
		++begin;
		--end;
	}
}

template<typename Elemtype>
void MyArray<Elemtype>::Insert_sort()
{
	if (size <= 0)
		return;
	for (int i = 0; i < size - 1; ++i)
	{
		int end = i;
		Elemtype temp = arr[end + 1];
		while (end >= 0)
		{
			if (arr[end] > temp)
			{
				arr[end + 1] = arr[end];
				--end;
			}
			else
			{
				break;
			}
		}
		arr[end + 1] = temp;     //有两种可能
		//1.待插入元素找到应插入位置(break跳出循环到此)
		//2.待插入元素比当前有序序列中的所有元素都小(while循环结束后到此)
	}

}

template<typename Elemtype>
void MyArray<Elemtype>::Shell_sort()
{
	int gap = size / 2;
	while (gap > 0)   //对于gap的都要插入排序
	{
		for (int i = 0; i < size - gap; ++i)
		{
			int end = i;
			Elemtype temp = arr[end + gap];
			while (end >= 0)
			{
				if (arr[end] > temp)
				{
					arr[end + gap] = arr[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = temp;
		}
		gap /= 2;
	}
}

template<typename Elemtype>
void MyArray<Elemtype>::Quick_sort(int begin, int end)
{
	//只有一个数或区间不存在
	if (begin >= end)
		return;
	int left = begin;
	int right = end;
	//选左边为key
	int keyi = begin;
	while (begin < end)
	{
		//右边选小   等号防止和key值相等    防止顺序begin和end越界
		while (arr[end] >= arr[keyi] && begin < end)
		{
			--end;
		}
		//左边选大
		while (arr[begin] <= arr[keyi] && begin < end)
		{
			++begin;
		}
		//小的换到右边,大的换到左边
		Swap(&arr[begin], &arr[end]);
	}
	Swap(&arr[keyi], &arr[end]);
	keyi = end;
	//[left,keyi-1]keyi[keyi+1,right]
	Quick_sort(left, keyi - 1);
	Quick_sort(keyi + 1, right);
}

template<typename Elemtype>
void MyArray<Elemtype>::Radix_sort()
{
	if (size <= 0)
		return;
	int i, j, num, tempIndex;//准备计数和下标记录

	//1、准备桶子
	Elemtype** tempArr = new Elemtype * [10];//动态实现二维数组
	for (i = 0; i < 10; ++i)
	{
		tempArr[i] = new Elemtype[size];
	}
	//2、循环
	for (int n = 1; n < 10000; n *= 10)//最外层循环 - 最大数位数
	{
		//2.1、桶子初始化
		for (i = 0; i < 10; ++i)
		{
			for (j = 0; j < size; ++j)
			{
				//初始化给的值一定不会出现在数据当中
				tempArr[i][j] = -1;
			}
		}
		//2.2、数据入桶
		for (i = 0; i < size; ++i)
		{
			//重点
			tempIndex = (arr[i] / n) % 10;//桶子编号
			tempArr[tempIndex][i] = arr[i];//入桶
		}
		//2.3、数据出桶
		num = 0;//计数初始化
		//数据取出 - 竖着遍历的
		for (i = 0; i < 10; ++i)//列
		{
			for (j = 0; j < size; ++j)//行
			{
				if (tempArr[i][j] != -1)
				{
					arr[num++] = tempArr[i][j];
				}
				//不要else break;
			}
		}
	}
}

template<typename Elemtype>
void MyArray<Elemtype>::Merge_sort(int left, int right)
{
	if (left >= right)
		return;
	int mid = left + ((right - left) >> 1);
	Merge_sort(left, mid);
	Merge_sort(mid + 1, right);
	Merge_in_arr(left, mid, right);
}

template<typename Elemtype>
void MyArray<Elemtype>::Merge_in_arr(int left, int mid, int right)
{
	//2.1、准备辅助数组 - 三个游标 左右区间 辅助数组
	int length = right - left + 1;//确定当前元素量
	int* pData = new int[length];
	//初始化
	memset(pData, 0, sizeof(int) * length);

	//游标
	int low = left;//左
	int hig = mid + 1;//右
	int index = 0;//辅助

	//2.2、合并过程 - 两个区间至少完成一个的遍历
	//不清楚有多少次
	while (low <= mid && hig <= right)
	{
		//左区间存在元素并且比右区间的小 落下
		while (low <= mid && arr[low] <= arr[hig])
		{
			pData[index++] = arr[low++];
		}
		//右区间存在元素并且比左区间的小 落下
		while (hig <= right && arr[hig] < arr[low])
		{
			pData[index++] = arr[hig++];
		}
	}
	//出循环,这就说明区间至少有一个已经遍历完了
	//2.3、剩下的部分直接拷贝过来
	if (low <= mid)//左区间有剩
		memmove(&pData[index], &arr[low], sizeof(int) * (mid - low + 1));
	if (hig <= right)//右区间有剩
		memmove(&pData[index], &arr[hig], sizeof(int) * (right - hig + 1));

	//3、把辅助数组里面的数据拷贝给原数组
	memmove(&arr[left], pData, length * sizeof(int));
	delete[] pData;//过河拆桥
	pData = nullptr;
}


template<typename Elemtype>
Elemtype MyArray<Elemtype>::Binary_search(Elemtype data)
{
	int left = 0, right = size - 1, mid;
	while (left <= right)
	{
		mid = left + ((right - left) >> 1);
		if (data == arr[mid])   return mid;
		if (data > arr[mid])    left = mid + 1;
		if (data < arr[mid])    right = mid - 1;
	}
	return -1;
}

主函数测试

#include <iostream>
#include "MySort_vector.hpp"
#define T int  //可以修改模板类型

int main() {
	T a;
	std::cin >> a;
	MyArray<T> Arr(a);
	Arr.Array_init();
	//Arr.Bubble_sort();
	//Arr.Select_sort();
	//Arr.Insert_sort();
	//Arr.Shell_sort();
	//Arr.Quick_sort(0,a-1);
	//Arr.Radix_sort();
	Arr.Merge_sort(0, a - 1);
	Arr.show();
	std::cout << Arr.Binary_search(4) << std::endl;

	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值