九大数据结构排序算法的实现
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 : 定义控制台应用程序的入口点。 // #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
注释:上面提供的基数排序仅能对相同位数的十进制数序列排序。