数据结构之九大排序算法C++

  九大数据结构排序算法的实现

targetver.h

#pragma once

// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。

// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
// WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。

#include <SDKDDKVer.h>


stdafx.h

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//
#define _AFXDLL
#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>



// TODO:  在此处引用程序需要的其他头文件
#include<iostream>
#include<fstream>
#include<string>
#include<afxwin.h>

using namespace std;

static const int CMAX_N = 100;

//剩余排序
class CData
{
public:
	int CKey_1;//使用该关键字
	int CKey_2;//未使用
	int CKey_3;//未使用
};

//基数排序数据节点
class _CList
{
public:
	char CData[2];//各个位置
	int CDataNum;//数据位数
	class _CList *next;
};

//排序
class CSortFunction
{
public:
	//构造
	CSortFunction(string CReadName, string CWriteName);
	//析构
	~CSortFunction();
	//警告信息
	inline void CWarnings();
	//获取文件数据
	void CGetArray();
	//获取文件数据
	void CGetFileData(string CRadixFileName,string CWriteRadixFileName);
	//基数排序写入
	bool CWriteRadix();	
	//写入排序后数据
	bool CWriteArray();
	//直接插入排序
	void CInsertSort();
	//折半插入排序
	void CHalfInsertSort();
	//希尔排序
	void CShellSort();
	//冒泡排序
	void CBubbleSort();
	//快速排序
	void CQuickSort();
	//选择排序
	void CSelectSort();
	//堆排序
	void CHeapSort();
	//归并排序
	void CMergeSort();
	//基数排序
	void CRadixSort();
private:
	CData *CArray;
	int CLength;
	string CReadName;
	string CWriteName;
	ifstream CReadFile;
	ofstream CWriteFile;
	_CList *list;
	_CList *CTmp = nullptr;

	//快速排序
	void PriCQuickSort(CData* CArray, int CStart, int CEnd);

	//堆重构
	void CSift(CData* CArray, int low, int high);

	//归并子表
	void CMerge(CData* CArray, int low, int mid, int high);

	//归并整张表
	void CMergePass(CData* CArray, int CChildLength, int CLength);
};


stdafx.cpp

// stdafx.cpp : 只包括标准包含文件的源文件
// AllSortFunction.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息

#include "stdafx.h"

// TODO:  在 STDAFX.H 中
// 引用任何所需的附加头文件,而不是在此文件中引用

//构造
CSortFunction::CSortFunction(string CReadName, string CWriteName)
{
	this->CReadName = CReadName;//读取文件名
	this->CWriteName = CWriteName;//写入文件名
	CArray = (CData *)malloc(sizeof(CData)*CMAX_N);//申请空间
	CLength = 0;//数组长度
}

//析构
CSortFunction::~CSortFunction()
{
	//释放基数排序所用空间
	_CList *CTmpList_r = list, *CTmpList_p = CTmpList_r->next;
	while (CTmpList_p != NULL)
	{
		free(CTmpList_r);
		CTmpList_r = CTmpList_p;
		CTmpList_p = CTmpList_p->next;
	}
	free(CTmpList_p);
	//释放其他排序所用空间
	free(CArray);
}


//警告
inline void CSortFunction::CWarnings()
{
	MessageBox(NULL, _T("No Data Found!"), _T("Warning"), 1);//无原始数据文件
	exit(0);
}


//获取数据
void CSortFunction::CGetArray()
{
	CReadFile.open(CReadName, ios::in);
	if (CReadFile.is_open())
	{
		int CfData, i = 0;
		while (!CReadFile.eof() && (CReadFile >> CfData).good())
		{
			CArray[i].CKey_1 = CfData;//读入数据
			i++;
		}
		CLength = i;//数组长度
	}
	else
	{
		CSortFunction::CWarnings();//警告,无原始数据文件
	}
	CReadFile.close();
}

//写入排序数据

bool CSortFunction::CWriteArray()
{
	CWriteFile.open(CWriteName, ios::out|ios::app);
	CWriteFile << "----------" << endl;
	for (int i = 0; i < CLength; i++)
	{
		CWriteFile << CArray[i].CKey_1 << endl;
	}
	CWriteFile.close();
	return true;
}


//直接插入排序
void CSortFunction::CInsertSort()
{
	for (int i = 1; i < CLength; i++)
	{
		CData tmp = CArray[i];
		int j = i - 1;
		//从有序序列末尾开始,若小于末尾,则后移覆盖
		while (j >= 0 && tmp.CKey_1 < CArray[j].CKey_1)
		{
			CArray[j + 1] = CArray[j];
			j--;
		}
		//正确位置
		CArray[j + 1] = tmp;
	}
}

//折半插入排序
void CSortFunction::CHalfInsertSort()
{
	int low, high, mid;
	for (int i = 1; i < CLength; i++)
	{
		CData tmp = CArray[i];
		low = 0; high = i - 1;
		//折半查找
		while (low <= high)
		{
			mid = (low + high) / 2;
			if (tmp.CKey_1 < CArray[mid].CKey_1)
			{
				high = mid - 1;
			}
			else
			{
				low = mid + 1;
			}
		}
		//后移插入正确位置
		for (int j = i - 1; j>high; j--)
		{
			CArray[j + 1] = CArray[j];
		}
		CArray[high + 1] = tmp;
	}
}

//希尔排序
void CSortFunction::CShellSort()
{
	//直接插入排序间隔为1,希尔排序间隔增大
	int gap = CLength / 2;//分割标志
	while (gap > 0)
	{
		for (int i = gap; i < CLength; i++)
		{
			CData tmp = CArray[i];
			int j = i - gap;
			while (j >= 0 && tmp.CKey_1 < CArray[j].CKey_1)
			{
				CArray[j + gap] = CArray[j];
				j -= gap;
			}
			CArray[j + gap] = tmp;
		}
		gap /= 2;
	}
}

//冒泡排序
void CSortFunction::CBubbleSort()
{
	bool CExchange;//优化判断是否有数据交换
	for (int i = 0; i < CLength - 1; i++)
	{
		CExchange = false;
		for (int j = CLength - 1; j>i; j--)
		{
			//后一位小于前一位,交换位置
			if (CArray[j].CKey_1 < CArray[j - 1].CKey_1)
			{
				CData tmp = CArray[j];
				CArray[j] = CArray[j - 1];
				CArray[j - 1] = tmp;
				CExchange = true;
			}
		}
		//若某一趟没有发生交换,排序结束
		if (!CExchange)
		{
			return;
		}
	}
}

//快速排序
void CSortFunction::PriCQuickSort(CData* CArray,int CStart,int CEnd)
{
	int i = CStart, j = CEnd;
	CData tmp;
	if (CStart < CEnd)
	{
		tmp = CArray[CStart];
		while (i != j)
		{
			//从右到左
			while (j>i&&CArray[j].CKey_1 >= tmp.CKey_1)
			{
				j--;
			}
			CArray[i] = CArray[j];
			//从左到右
			while (i<j&&CArray[i].CKey_1 <= tmp.CKey_1)
			{
				i++;
			}
			CArray[j] = CArray[i];
		}
		CArray[i] = tmp;
		//递归左右两侧
		PriCQuickSort(CArray, CStart, i - 1);
		PriCQuickSort(CArray, i + 1, CEnd);
	}
}

//快排
void CSortFunction::CQuickSort()
{
	PriCQuickSort(CArray, 0, CLength-1);
}

//选择排序
void CSortFunction::CSelectSort()
{
	for (int i = 0; i < CLength - 1; i++)
	{
		int k = i;
		//后i后存在更小值,则改变k值为该值下标
		for (int j = i + 1; j<CLength; j++)
		{
			if (CArray[j].CKey_1 < CArray[k].CKey_1)
			{
				k = j;
			}
		}
		//若发生改变,则交换
		if (k != i)
		{
			CData tmp = CArray[i];
			CArray[i] = CArray[k];
			CArray[k] = tmp;
		}
	}
}

//堆重构
void CSortFunction::CSift(CData* CArray, int low, int high)
{
	//位置i所在为双亲节点,j为左节点,j+1为右节点
	int i = low, j = 2 * i;
	CData tmp = CArray[i];
	while (j <= high)
	{
		//若右节点大于左节点,j指向右节点
		if (j < high&&CArray[j].CKey_1 < CArray[j + 1].CKey_1)
		{
			j++;
		}
		//若左右节点中较大值大于双钱节点,交换值和下标
		if (tmp.CKey_1 < CArray[j].CKey_1)
		{
			CArray[i] = CArray[j];
			i = j;
			j = 2 * i;
		}
		else
		{
			break;
		}
	}
	CArray[i] = tmp;
}

//堆排序
void CSortFunction::CHeapSort()
{
	//初始化堆
	for (int i = (CLength) / 2; i >= 0; i--)
	{
		CSift(CArray, i, CLength-1);
	}
	//排序
	for (int i = CLength-1; i >= 1; i--)
	{
		CData tmp = CArray[0];
		CArray[0] = CArray[i];
		CArray[i] = tmp;
		CSift(CArray, 0, i-1);//重构堆
	}
}

//归并子表
void CSortFunction::CMerge(CData* CArray, int low, int mid, int high)
{
	CData *CTmpArray;
	int i = low, j = mid + 1, k = 0;
	CTmpArray = (CData *)malloc(sizeof(CData)*(high - low + 1));
	while (i <= mid&&j <= high)
	{
		//向CTmpArray中存入第一段
		if (CArray[i].CKey_1 <= CArray[j].CKey_1)
		{
			CTmpArray[k] = CArray[i];
			i++; k++;
		}
		else//存第二段
		{
			CTmpArray[k] = CArray[j];
			j++; k++;
		}
	}
	//复制第一段余下部分
	while (i <= mid)
	{
		CTmpArray[k] = CArray[i];
		i++; k++;
	}
	//复制第二段余下部分
	while (j <= high)
	{
		CTmpArray[k] = CArray[j];
		j++; k++;
	}
	//拷贝回原数组
	for (k = 0, i = low; i <= high; k++, i++)
	{
		CArray[i] = CTmpArray[k];
	}
	free(CTmpArray);
}

//归并整张表
void CSortFunction::CMergePass(CData* CArray, int CChildLength, int CLength)
{
	int i;
	//归并CChildLength长的相邻子表
	for (i = 0; i + 2 * CChildLength - 1 < CLength; i = i + 2 * CChildLength)
	{
		CMerge(CArray, i, i + CChildLength - 1, i + 2 * CChildLength - 1);
	}
	//归并子表
	if (i + CChildLength - 1 < CLength)
	{
		CMerge(CArray, i, i + CChildLength - 1, CLength - 1);
	}
}

//归并排序
void CSortFunction::CMergeSort()
{
	for (int length = 1; length < CLength; length = length * 2)
	{
		CMergePass(CArray, length, CLength);
	}
}

//获取文件数据
void CSortFunction::CGetFileData(string CRadixFileName, string CWriteRadixFileName)
{
	CReadName = CRadixFileName;//读入数据文件名
	CWriteName = CWriteRadixFileName;//写入数据文件名

	//尾插法构造链表
	_CList *CTmpList_r, *CTmpList_p;
	list = (_CList *)malloc(sizeof(_CList));
	CTmpList_r = list;

	string CfData;
	CReadFile.open(CReadName, ios::in);
	if (CReadFile.is_open())
	{
		while (!CReadFile.eof() && (CReadFile >> CfData).good())
		{
			int j = 0;
			CTmpList_p = (_CList *)malloc(sizeof(_CList));
			CTmpList_p->CDataNum = CfData.length();//获取数据位数
			while (CfData.length())
			{
				CTmpList_p->CData[j] = CfData[CfData.length()-1];//倒叙写入数据
				CfData.assign(CfData.substr(0, CfData.length() - 1));//重构数据串
				j++;
			}
			CTmpList_r->next = CTmpList_p;
			CTmpList_r = CTmpList_p;
		}
		CTmpList_r->next = nullptr;
		CReadFile.close();
	}
	else
	{
		CWarnings();
	}
}


//基数排序
void CSortFunction::CRadixSort()
{
	_CList *CHead[10], *CTail[10], *CTmp_r = nullptr;
	CTmp = list->next;
	//分散遍历排序
	for (int i = 0; i < CTmp->CDataNum; i++)
	{
		//初始化为空
		for (int j = 0; j < 10; j++)
		{
			CHead[j] = CTail[j] = nullptr;
		}
		//按个位/十位/百位...依次排序,循环次数定位数据位数次
		while (CTmp!=NULL)
		{
			int k = CTmp->CData[i] - '0';
			if (CHead[k] == NULL)
			{
				CHead[k] = CTail[k] = CTmp;
			}
			else
			{
				CTail[k]->next = CTmp;
				CTail[k] = CTmp;
			}
			CTmp = CTmp->next;
		}
		//收集排序后序列
		CTmp = NULL;
		for (int j = 0; j < 10; j++)
		{
			if (CHead[j] != NULL)
			{
				if (CTmp == NULL)
				{
					CTmp = CHead[j];
					CTmp_r = CTail[j];
					
				}
				else
				{
					CTmp_r->next = CHead[j];
					CTmp_r = CTail[j];
					
				}
			}
		}
		CTmp_r->next = NULL;
	}
}

//基数排序写入
bool CSortFunction::CWriteRadix()
{
	CWriteFile.open(CWriteName, ios::out);
	_CList *CTmpList_r = CTmp;
	while (CTmpList_r != NULL)
	{
		//倒叙写入,获取正序数
		CWriteFile << CTmpList_r->CData[1] << CTmpList_r->CData[0] << endl;
		CTmpList_r = CTmpList_r->next;
	}
	CWriteFile.close();
	return true;
}

AllSortFunction.cpp(main文件)

// AllSortFunction.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
	CSortFunction sort("read.txt", "sort.txt");
	sort.CGetArray();//读数据
	sort.CInsertSort();//直接插入排序
	if (sort.CWriteArray())//写数据
	{
		cout << "直接插入排序 OK." << endl;
	}
	sort.CHalfInsertSort();//折半插入排序
	if (sort.CWriteArray())//写数据
	{
		cout << "折半插入排序 OK." << endl;
	}
	sort.CShellSort();//希尔排序
	if (sort.CWriteArray())//写数据
	{
		cout << "希尔排序 OK." << endl;
	}
	sort.CBubbleSort();//冒泡排序
	if (sort.CWriteArray())//写数据
	{
		cout << "冒泡排序 OK." << endl;
	}
	sort.CQuickSort();//快速排序
	if (sort.CWriteArray())//写数据
	{
		cout << "快速排序 OK." << endl;
	}
	sort.CSelectSort();//选择排序
	if (sort.CWriteArray())//写数据
	{
		cout << "选择排序 OK." << endl;
	}
	sort.CHeapSort();//堆排序
	if (sort.CWriteArray())//写数据
	{
		cout << "堆排序 OK." << endl;
	}
	sort.CMergeSort();//归并排序
	if (sort.CWriteArray())//写数据
	{
		cout << "归并排序 OK." << endl;
	}
	sort.CGetFileData("radix.txt", "solveRadix.txt");//获取基数排序数据
	sort.CRadixSort();//基数排序
	//写入文件
	if (sort.CWriteRadix())
	{
		cout << "基数排序 OK." << endl;
	}
	return 0;
}


测试运行



read.txt



radix.txt



sort.txt



solveradix.txt



注释:上面提供的基数排序仅能对相同位数的十进制数序列排序。


  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构中的八大排序算法,是指常见的八种用于对数据进行排序的算法。这八种算法分别是冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序和基数排序。 冒泡排序是一种简单的排序算法,通过不断比较和交换相邻元素的位置,使得最大(或最小)的元素逐渐往后(或往前)移动。 选择排序是一种简单直观的排序算法,每次选择未排序序列中最小(或最大)的元素,放到已排序序列的末尾。 插入排序是一种简单直观的排序算法,将一个待排序的元素插入到已部分排序的数列中的合适位置。 希尔排序是一种改进的插入排序算法,通过将待排序数列分组,并对每个分组进行插入排序,然后逐渐减小分组规模,最后进行一次插入排序。 归并排序是一种分治思想的排序算法,将待排序数列不断分割成较小的数列,然后再将这些较小的数列按照顺序进行合并。 快速排序是一种分治思想的排序算法,通过选择一个中间的基准元素,将数列分割成两部分,然后分别对这两部分进行排序。 堆排序是一种利用堆这种数据结构排序算法,通过将待排序数列构建成一个大(或小)顶堆,然后逐步将堆顶元素与最后一个元素交换,并调整堆结构。 计数排序是一种非比较型的排序算法,通过统计待排序数列中每个元素出现的次数,然后依次输出即可。 基数排序是一种非比较型的排序算法,通过对待排序数列的每个位进行排序,依次从低位到高位进行。 这里简单介绍了八大排序算法的基本思想和实现方法。在实际应用中,不同的排序算法适用于不同的场景和要求,我们需要根据具体情况选择合适的算法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值