数据结构里的一些排序算法及其初级优化 v1.0

原创 2012年03月25日 02:13:03

以下代码包含 冒泡排序、选择排序、插入排序、谢尔排序、堆排序、归并排序、快速排序

这伙是测试用数据类
waitForSort.h

#ifndef WAITFORSORT_H
#define WAITFORSORT_H

#include <iostream>
#include "time.h"

const int MAXSIZE = 1000;

class waitForSort
{
public:
	int data[MAXSIZE];
	int length;
	waitForSort(const int, const int);
	void swap(const int, const int);
	void outPut();	
};

#endif

waitForSort.cpp
#include "waitForSort.h"

waitForSort::waitForSort(const int n, const int range) : length(n){
	srand(static_cast<int>(time(0)));
	for(int iter = 0; iter != n; ++iter)
		data[iter] = rand() % range;
}

void waitForSort::swap(const int a, const int b){
	int temp = data[a];
	data[a] = data[b];
	data[b] = temp;
}

void waitForSort::outPut(){
	for(int iter = 0; iter != length; ++iter){
		if(iter % 10 == 0)
			std::cout<<std::endl;
		std::cout<<data[iter]<<"  ";
	}
}

ok,上算法...

Sorting.h

#include "waitForSort.h"
#include <math.h>
/**********************冒泡排序(改)**********************/
void BubbleSort(waitForSort &L){
	const int NUM = L.length - 1;//空间换时间
	bool flag = true;
	for(int iter = 0; iter != NUM && flag; iter++){
		flag = false;
		for(int r = NUM; r != iter; r--){			
			if(L.data[r] < L.data[r - 1]){
				L.swap(r - 1, r);
				flag = true;
			}				
		}			
	}
}

/**********************选择排序**********************/
void SelectSort(waitForSort &L){
	const int NUM = L.length - 1;
	int min;
	for(int iter = 0; iter != NUM; iter++){
		min = iter;
		for(int r = iter + 1; r != L.length; r++)
			if(L.data[r] < L.data[min]){
				min = r;
			}
		if(min != iter)
			L.swap(min, iter);
	}	
}

/**********************插入排序**********************/
void InsertSort(waitForSort &L){
	int temp, iter, r;
	const int NUM = L.length - 1;
	for(iter = 0; iter != NUM; iter++){
		if(L.data[iter] > L.data[iter + 1]){
			temp = L.data[iter + 1];
			for(r = iter; L.data[r] > temp && r >= 0; r--)//此处要注意,防止越界
				L.data[r + 1] = L.data[r];
			L.data[r + 1] = temp;
		}
	}
}

/**********************谢尔排序**********************/
//谢尔排序可以看作选择排序的改进版,基本思想是通过元素的大
//范围跃迁减少不必要的迭代次数,从而降低时间复杂度。
void InsertShell(const int &gap, const int &NUM, waitForSort &L){
	int iter, r, temp;
	for(iter = gap; iter <= NUM; iter++){
		temp = L.data[iter];
		for(r = iter; r >= gap && L.data[r - gap] > temp; r -= gap)
			L.data[r] = L.data[r - gap];
		L.data[r] = temp;
	}
}

void ShellSort(waitForSort &L, int key){
	const int NUM = L.length - 1;
	int k = 0, p[20];
	int sedgewick[] = {//实践中总结出来的一个比较高效的增量集合   
            1073643521, 603906049, 268386305, 150958081, 67084289,  
            37730305, 16764929, 9427969, 4188161, 2354689,  
            1045505, 587521, 260609, 146305, 64769,  
            36289, 16001, 8929, 3905, 2161,  
            929, 505, 209, 109, 41,  
            19, 5, 1, 0};  

	switch(key){

	case 1://使用谢尔增量
		for(int gap = NUM / 2; gap > 0; gap /= 2)
			InsertShell(gap, NUM, L);
		break;

	case 0://使用Hibbard增量		
		for(int iter = 0; iter != 20; iter++, k++){		
			p[iter] = pow(static_cast<double>(2), iter + 1) - 1;
			if(p[iter] > NUM)
				break;	
		}
		while(k != 0){
			InsertShell(p[--k], NUM, L);
		}		
		break;

	case -1://使用经验增量
		while(sedgewick[k] > NUM)
			k++;
		k--;
		while(sedgewick[k] > 0){
			InsertShell(sedgewick[k++], NUM, L);
		}
		break;
	}
}

/**********************堆排序**********************/
//堆,本质上是拥有特殊性质的完全二叉树

//makeHeap函数,将处于第i层的节点与其 已形成大顶堆
//的子树调整为一个新的大顶堆!
void makeHeap(waitForSort &L, int start, int end){//start, end均为第x个元素(A类),为(下标数 + 1)
	int temp;
	temp = L.data[start - 1];
	for(int iter = 2 * start; iter <= end; iter *= 2){//attention! iter为A类数据
		if(iter < end && L.data[iter - 1] < L.data[iter])//若left child < right child
			++iter;
		if(temp >= L.data[iter - 1])//可以看到,这里运用了选择排序的思想
			break;
		L.data[start - 1] = L.data[iter - 1];
		start = iter;
	}
	L.data[start - 1] = temp;
}

void HeapSort(waitForSort &L){
	int iter;//A类数据
	for(iter = L.length / 2; iter > 0; --iter)//iter指向的是每个拥有子树的节点,从后往前遍历
		makeHeap(L, iter, L.length);
	for(iter = L.length; iter > 1; --iter){
		L.swap(0, iter - 1);//将大顶堆的根节点(当前最大值)移至数据尾部
		makeHeap(L, 1, iter - 1);
	}		
}

/**********************归并排序(递归版本)**********************/
void Merge(int left[], int right[], int a, int b, int c){//将left[a to b] 与 left[b + 1 to c]归并到right[a to b], abc为数组下标
	int R_iter = a, A_stop = b;
	for(++b; a <= A_stop && b <= c; ++R_iter)
		right[R_iter] = left[a] < left[b] ? left[a++] : left[b++];//将下标a,b指向的值的较小者归入rigth[r_iter]
	for(; a <= A_stop; ++R_iter)
		right[R_iter] = left[a++];//将剩余值归并
	for(; b <= c; ++R_iter)
		right[R_iter] = left[b++];	//同上
}

void MSort(int left[], int right[], int a, int b){//分割元素后归并
	  if(a == b){
		  right[a] = left[a];
		  return;
	  }
	  else{
		int TempSave[MAXSIZE];
		int mid = (a + b) / 2;
		MSort(left, TempSave, a, mid);
		MSort(left, TempSave, mid + 1, b);
		Merge(TempSave, right, a, mid, b);		
	  }
}

void MergeSort_1(waitForSort &L){//这种编程方法有利于封装
	MSort(L.data, L.data, 0, L.length - 1);
}

/**********************归并排序(迭代版本)**********************/
//俗话说,能不用递归就不用递归,为了保证空间跟时间复杂度,下面
//给出迭代版本

//将重用上面定义的Merge方法
void MergeStep(int left[], int right[], int width, int end){//注意,end为A类数据
	int i = 1;
	while(i <= end - 2 * width + 1){
		Merge(left, right, i - 1, i + width - 2, i + 2 * width - 2);//宽度为width的数据两两归并
		i += 2 * width;
	}
	if(i < end - width + 1)
		Merge(left, right, i - 1, i + width - 2, end - 1);
	else
		for(int iter = i - 1; iter < end; ++iter)//此处可用以防止出现width>end的情况出现
			right[iter] = left[iter];
}

void MergeSort_2(waitForSort &L){
	int *p = new int[L.length];//用同一片地址来存储中间数据~
	int k = 1;
	while(k < L.length){
		MergeStep(L.data, p, k, L.length);
		k *= 2;
		MergeStep(p, L.data, k, L.length);
		k *= 2;
	}
}

/**********************快速排序**********************/
//思路很简单,没啥好说的..
int Location(waitForSort &L, int low, int high){
	int Key;
	Key = L.data[low];//简单的取首值
	while(low < high){
		while(low < high  && L.data[high] >= Key){
			--high;
		}
		L.swap(low, high);
		while(low < high && L.data[low] <= Key){
			++low;
		}
		L.swap(low, high);
	}
	return low;
}

void QuickSortRecursion(waitForSort &L, int low, int high){
	int pivot;//中轴
	if(low < high){
		pivot = Location(L, low, high);
		QuickSortRecursion(L, low, pivot - 1);
		QuickSortRecursion(L, pivot + 1, high);
	}
}

void QuickSort(waitForSort &L){
	QuickSortRecursion(L, 0, L.length - 1);
}

/**********************快排优化版**********************/
int better_Location(waitForSort &L, int low, int high){
	int Key;
	//Key = L.data[low];//简单的去首值
	//////////////////////////////////优化1////////////////////////////////////////////////////////
	int mid = (high + low) / 2;
	if(L.data[low] > L.data[high])
		L.swap(low, high);
	if(L.data[mid] > L.data[high])
		L.swap(mid, high);
	if(L.data[low] < L.data[mid])
		L.swap(mid, low);//low所指向的数为三数间的中间数,此为三数取中法。可考虑增加抽样率提高准确性
	Key = L.data[low];
	///////////////////////////////////////////////////////////////////////////////////////////////
	//////////////////////////////////优化2////////////////////////////////////////////////////////
	while(low < high){
		while(low < high  && L.data[high] >= Key){
			--high;
		}
		//L.swap(low, high);
		L.data[low] = L.data[high];
		while(low < high && L.data[low] <= Key){
			++low;
		}
		//L.swap(low, high);
		L.data[high] = L.data[low];
	}
	L.data[low] = Key;
	////////////////////////////////////////////////////////////////////////////////////////////////
	return low;
}
///////////////////////////////////////优化3///////////////////////////////////////////////////////
void better_QuickSortRecursion(waitForSort &L, int low, int high){
	int pivot;//中轴
	if((high - low) > 50){//超过50时用快排,否则直接插入排序
		while(low < high){
			pivot = better_Location(L, low, high);
			better_QuickSortRecursion(L, low, pivot - 1);
			low = pivot + 1;//优化尾递归
		}		
	}
	else
		InsertSort(L);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////

void better_QuickSort(waitForSort &L){
	better_QuickSortRecursion(L, 0, L.length - 1);
}




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

数据结构与算法(C#版)第二章 C#语言与面向对象技术(上)V1.0

由于本学期我给本科生上《数据结构与算法》这门课程,边上边把自己的教案进行总结,发到CSDN上面,希望大家多多指正。 这篇为第二章C#语言与面向对象技术(上)部分。

数据结构之排序算法(二)

在上一个博客里,说了一下插入类排序。今天和大家说一下交换类排序。交换类排序是一种基于交换的排序方法,主要介绍两种排序方法:冒泡排序(+改进)、快速排序1、冒泡排序 冒泡排序是一种简单的交换类排序方法...

数据结构排序算法

数据结构排序算法

  • 2014-06-09 12:36
  • 433B
  • 下载

数据结构之排序算法(四)

前面说了不少的排序算法了,今天有从书上看到了两个排序算法,这里准备把它们记录下来。今天写的两个排序算法是归并排序和基数排序1、归并排序 在使用归并排序时,将两个或两个以上的有序表合并成一个新的有序表...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)