一. 目的与背景知识
进行桶排序练习。
桶排序按总体将数据进行分组若干,组内插入排序。组内元素通过链表连接。
二. 代码实现
调整数据生成类可以生成带小数位的浮点数。
TestDataCreator(ArrayType nArrayType = PositiveArray){
Sleep(1000);//暂停一秒,否则产生相同的随机种子
srand((unsigned int)time(NULL));//产生一个随即种子
DataType Tbase = DataType();//产生一个初始基准值。
if (nSize == 0) return;
switch (nArrayType){
case PositiveArray:
//正序数组,从前向后递增
for (int i = 0; i < nSize; i++){
if (i != 0){
pArray[i] = pArray[i - 1] + GetRandomDigit(rand(), rand());
}
else{
pArray[i] = Tbase + GetRandomDigit(rand(), rand());
}
}
break;
case NegativeArray:
//逆序数组从后向前递增
for (int i = nSize - 1; i >= 0; i--){
if (i != nSize - 1){
pArray[i] = pArray[i + 1] + GetRandomDigit(rand(), rand());
}
else{
pArray[i] = Tbase + GetRandomDigit(rand(), rand());
}
}
break;
case RandomArray:
//正序数组,从前向后递增
for (int i = 0; i < nSize; i++){
pArray[i] = Tbase + GetRandomDigit(rand(), rand());
}
break;
}
};
DataType GetRandomDigit(int RandLeft, int RoundRight=0){
return RandLeft % (nSize + 1) + (RoundRight % (nSize + 1)) / (nSize + 1.1);
}
桶排序实现代码
struct Node{
public:
T keyValue;
Node<T>* next;
Node(){ keyValue = T(0); next = NULL; };
~Node(){};
};
//桶排序
void BucketSort(T testArray[], int nSize){
LogInfo<T> log = LogInfo<T>();
log.ShowState("原始数组为:");
log.ShowArray(testArray, nSize);
//一次遍历获取最大值
T TMax = testArray[0];
for (int i = 0; i < nSize; i++){
if (testArray[i]>TMax){
TMax = testArray[i];
}
}
int nNodes = (int)((TMax+3) / 3);
Node<T>* nodeArray = new Node<T>[nNodes];
Node<T>* CurNode;
Node<T>* tmp;
for (int i = 0; i < nSize; i++){
CurNode = &nodeArray[(int)(testArray[i] / 3)];
tmp = new Node<T>();
tmp->keyValue = testArray[i];
while (CurNode != NULL){
if (CurNode->next == NULL){
tmp->next=CurNode->next;
CurNode->next = tmp;
break;
}
else if (CurNode->next->keyValue > tmp->keyValue){
tmp->next = CurNode->next;
CurNode->next = tmp;
break;
}
else{
CurNode = CurNode->next;
}
}
}
//将桶中数据放回数据原位置
int j(0);
for (int i = 0; i < nNodes; i++){
CurNode = nodeArray[i].next;
while (CurNode != NULL){
testArray[j++] = CurNode->keyValue;
CurNode = CurNode->next;
}
}
log.ShowState("最终数组为:");
log.ShowArray(testArray, nSize);
delete[] nodeArray;
if (CurNode != NULL){ delete CurNode; }
if (tmp != NULL){ delete tmp; }
}
测试代码
using namespace Test;
using namespace MyAlgorithm;
using namespace std;
LogInfo<double> log = LogInfo<double>();
Sort<double> sortTest = Sort<double>();
log.ShowState("测试桶排序");
log.ShowLine();
log.ShowState("测试正序数组========================");
log.ShowLine();
TestDataCreator<double, N_MAX> testArray = TestDataCreator<double, N_MAX>(PositiveArray);
sortTest.BucketSort(testArray.GetArray(), testArray.GetSize());
log.ShowState("测试降序数组========================");
log.ShowLine();
testArray = TestDataCreator<double, N_MAX>(NegativeArray);
sortTest.BucketSort(testArray.GetArray(), testArray.GetSize());
log.ShowState("测试随机数组========================");
log.ShowLine();
testArray = TestDataCreator<double, N_MAX>(RandomArray);
sortTest.BucketSort(testArray.GetArray(), testArray.GetSize());
int nWait;
cin >> nWait;
return 0;
结果输出
三. 遇到问题
1、链表结构的构造函数没有加空函数体,导致无效标识符
2、桶排序只查证存在链表这一种比较好的实现,其余实现存在问题。
3、无法产生浮点数。
4、保证桶至少有一个数据,否则报位置写错误。
5、没有释放指针,释放后由于SDL(安全开发声明周期检查)导致无法编译通过,报4703错误。
四. 经验总结
1、函数必须有函数体。
2、浮点数必须从整形做提升。
3、经常记得释放不用的指针对象。
4、桶排序的空间效率O((b+N)*2),算法稳定。时间效率O(N)。
5、桶排序依赖于假设数据均匀分布。桶排序是非常快的排序方式。
五. 后续任务
排序算法暂时告一段落,后续任务主要以算法导论为学习主导,学习算法分析。附加C++编程练习。
后续计划:
1、每周两篇算法导论练习,一篇C++基础练习。
2、练习算法导论,算法基础章节的练习题。
3、练习C++ primary plus 输出、输入和文件章节。
计划说明:
编程基础性东西,可以通过拔高产生问题,带着问题去学习,因此C++练习从后向前练习。
算法必须层层铺垫,提高自己算法分析方面的能力。因此必须从前向后练习。
六. 参考文献
1、算法导论
2、 桶排序http://www.2cto.com/kf/201303/196090.html
3、经典排序算法 - 桶排序Bucket sorthttp://www.cnblogs.com/kkun/archive/2011/11/23/2260267.html