C++ 排序算法


这些排序算法的定义等等自己去百度百科,这里只有代码

排序类的定义

/************************
排序类Sort的类定义
*************************/
class Sort
{
public:
	Sort(int r[ ], int n); //构造函数,生成待排序序列
	~Sort( ); //析构函数
	
	void InsertSort( ); //直接插入排序
	void ShellSort( ); //希尔排序
	void BubbleSort( ); //起泡排序
	void QuickSort(int first, int last); //快速排序
	void SelectSort( ); //简单选择排序
	void HeapSort( ); //堆排序
	void MergeSort1(int first, int last); //二路归并递归排序
	void MergeSort2( ); //二路归并非递归排序
	void Print( ); //输出序列
private:
	int Partition(int first, int last); //快速排序,一次划分
	void Sift(int k, int last); //堆排序,堆调整
	void Merge(int first1, int last1, int last2); //归并排序,合并相邻有序序列
	void MergePass(int h); //归并排序,一趟归并
	
	int *data; //待排序序列,可以是数组
	int length;
};

Sort :: Sort(int r[ ], int n)
{
	data = new int[n];
	for (int i = 0; i < n; i++)
	data[i] = r[i];
	length = n;
}

Sort :: ~Sort( )
{
	delete[ ] data;
}

void Sort :: Print( )
{
	for (int i = 0; i < length; i++)
	cout << data[i] << " ";
}

直接插入排序 Straight Insertion Sort (稳定)

/***********************
直接插入排序算法
************************/
void Sort::InsertSort( )
{
	int i, j, temp;  //temp是一个值
	for (i = 1; i < length; i++) //排序进行length-1趟
	{
		temp = data[i]; //暂存待插记录
		for (j = i - 1; j >= 0 && temp < data[j]; j--) //寻找插入位置
			data[j + 1] = data[j];
		
		data[j + 1] = temp;
	}
}

希尔排序 Shell Sort (不稳定)

/******************
希尔排序算法
*******************/
void Sort::ShellSort( )
{
	int temp, d, i, j;
	for (d = length/2; d >= 1; d = d/2) //增量为d进行直接插入排序
	{
		for (i = d; i < length; i++) //进行一趟希尔排序
		{
			temp = data[i]; //暂存待插入记录
			for (j = i - d; j >= 0 && temp < data[j]; j = j - d)
				data[j + d] = data[j]; //记录后移d个位置
				
			data[j + d] = temp;
		}
	}
}

起泡排序 Bubble Sort(和冒泡不一样)(稳定)

/*******************
起泡排序算法
********************/
void Sort::BubbleSort( )
{
	int j, exchange, bound, temp;
	exchange = length - 1; //第一趟起泡排序的区间是[0~length-1]
	
	while (exchange != 0)
	{
		bound = exchange;
		exchange = 0;
		for (j = 0; j < bound; j++) //一趟起泡排序的区间是[0~bound]
			if (data[j] > data[j+1]) 
			{
				temp = data[j];
				data[j] = data[j+1];
				data[j+1] = temp;
				exchange = j; //记载每一次记录交换的位置
			}
	}
}

快速排序 Quick sort (不稳定)

一次划分算法

/*****************************
快速排序的一次划分算法
******************************/
int Sort::Partition(int first, int last)
{
	int i = first, j = last, temp; //初始化一次划分的区间
	while (i < j)
	{
		while (i < j && data[i] <= data[j]) 
			j--; //右侧扫描
		if (i < j) 
		{
			temp = data[i];
			data[i] = data[j]; 
			data[j] = temp;
			i++;
		}
		
		while (i < j && data[i] <= data[j])
			i++; //左侧扫描
			
		if (i < j) 
		{
			temp = data[i]; 
			data[i] = data[j]; 
			data[j] = temp;
			j--;
		}
	}
	return i; // i为轴值记录的最终位置
}

整个过程

/*******************
快速排序算法
********************/
void Sort::QuickSort(int first, int last)
{
	if (first >= last)
		return; //区间长度为1,递归结束
	else
	{
		int pivot = Partition(first, last); //一次划分
		QuickSort(first, pivot-1); //对左侧子序列进行快速排序
		QuickSort(pivot+1, last); //对右侧子序列进行快速排序
	}
}

简单选择排序 Simple Select Sort (不稳定)

/**********************
简单选择排序算法
***********************/
void Sort::SelectSort( )
{
	int i, j, index, temp;
	for (i = 0; i < length - 1; i++) //进行length-1趟简单选择排序
	{
		index = i;
		for (j = i + 1; j < length; j++) //在无序区中选取最小记录
			if (data[j] < data[index]) 
				index = j;
				
		if (index != i)
		{
		temp = data[i]; 
		data[i] = data[index]; 
		data[index] = temp;
		}
	}
}

堆排序 Heap Sort (不稳定)

图解排序算法(三)之堆排序

堆调整算法

将完全二叉树存储到 data[0] ~ data[length-1] 中(顺序存储,层序遍历的那种),则结点 data[i] 的左孩子是 data[2*i+2] ,堆调整算法的成员函数定义如下:

/*****************
堆调整算法
******************/
void Sort::Sift(int k, int last)
{
	int i, j, temp;
	i = k; j =2 * i + 1; // i是被筛选结点,j是i的左孩子
	
	while (j <= last) //筛选还没有进行到叶子
	{
		if (j < last && data[j] < data[j+1]) 
			j++; // j指向左右孩子的较大者
		if (data[i] > data[j])
			break; //已经是堆
		else
		{
			temp = data[i]; data[i] = data[j]; data[j] = temp;
			i = j; j = 2 * i + 1; //被筛结点位于原来结点j的位置
		}
	}
}

堆排序

最后结果是升序序列

/*****************
堆排序算法
******************/
void Sort::HeapSort( )
{
	int i, temp;
	for (i = ceil(length/2) - 1; i >= 0; i--) //从最后一个分支结点至根结点
		Sift(i, length-1) ;
	
	for (i = 1; i < length; i++)
	{
		temp = data[0]; data[0] = data[length-i]; data[length-i] = temp;
		Sift(0, length-i-1); //重建堆
	}
}

归并排序 Merge Sort

二路归并排序的递归算法(稳定)

/***********************
归并排序的递归算法
************************/
void Sort::MergeSort1(int first, int last)
{
	if (first == last)
		return; //待排序序列只有1个记录,递归结束
	else {
		int mid = (first + last)/2;
		
		MergeSort1(first, mid); //归并排序前半个子序列
		
		MergeSort1(mid+1, last); //归并排序后半个子序列
		
		Merge(first, mid, last); //将两个已排序的子序列合并
	}
}

将两个已排序的子序列合并

/*************************
合并相邻子序列算法
**************************/
void Sort::Merge(int first1, int last1, int last2)
{
	int *temp = new int[length]; //数组temp作为合并的辅助空间
	int i = first1, j = last1 + 1, k = first1;
	
	while (i <= last1 && j <= last2)
	{
		if (data[i] <= data[j])
		temp[k++] = data[i++]; //取较小者放入temp[k]
		else
		temp[k++] = data[j++];
	}
	
	while (i <= last1) //对第一个子序列进行收尾处理
		temp[k++] = data[i++];
	
	while (j <= last2) //对第二个子序列进行收尾处理
		temp[k++] = data[j++];
		
	for (i = first1; i <= last2; i++) //将合并结果传回数组r
		data[i] = temp[i];
		
	delete[ ] temp;
}

二路归并排序非递归算法

/**************************
归并排序的非递归算法
***************************/
void Sort::MergeSort2( )
{
	int h = 1; //初始时子序列长度为1
	while (h < length)
	{
		MergePass(h); //一趟归并排序
		h = 2 * h;
	}
}

/*******************!!!!!!!!!!!!!!!!!!
一趟归并算法
********************/
void Sort::MergePass(int h)
{
int i = 0;
while (i + 2 * h <= length) //待归并记录有两个长度为h的子序列
{
Merge(i, i+h-1, i+2*h-1);
i = i + 2 * h;
}
if (i + h < length)
Merge(i, i+h-1, length-1); //两个子序列一个长度小于h
}

各种排序技术的使用范例/总代码

(每次只能运行一次)

/************************************************
    排序类Sort的类定义、各种排序算法及使用范例 
*************************************************/
#include <iostream> 
#include <cmath>
using namespace std; 

class Sort
{
public:
    Sort(int r[ ], int n);                           //构造函数,生成待排序序列
    ~Sort( );                                   //析构函数
	void InsertSort( );                            //直接插入排序
	void ShellSort( );                            //希尔排序
	void BubbleSort( );                           //起泡排序
	void QuickSort(int first, int last);                //快速排序
	void SelectSort( );                            //简单选择排序
	void HeapSort( );                             //堆排序
	void MergeSort1(int first, int last);               //二路归并递归排序
	void MergeSort2( );                           //二路归并非递归排序
	void Print( );                                //输出序列 
private:
	int Partition(int first, int last);                   //快速排序,一次划分
	void Sift(int k, int last);                        //堆排序,堆调整
	void Merge(int first1, int last1, int last2);          //归并排序,合并相邻有序序列
	void MergePass(int h);                        //归并排序,一趟归并

    int *data;                                  //待排序序列
    int length;
};

void Sort::InsertSort( )          
{	
  	int i, j, temp;
  	for (i = 1; i < length; i++)                      //排序进行length-1趟
  	{ 
		temp = data[i];                                //暂存待插记录
		for (j = i - 1; j >= 0 && temp < data[j]; j--)     //寻找插入位置
			data[j + 1] = data[j];                
		data[j + 1] = temp;	
  	}
}

void Sort::BubbleSort( )      
{	
	int j, exchange, bound, temp;
	exchange = length - 1;           //第一趟起泡排序的区间是[0~length-1]
	while (exchange != 0)            
	{
		bound = exchange; exchange = 0;  
		for (j = 0; j < bound; j++)       //一趟起泡排序的区间是[0~bound]
			if (data[j] > data[j+1]) {
				temp = data[j]; data[j] = data[j+1]; data[j+1] = temp;
				exchange = j;           //记载每一次记录交换的位置
			}
	}
}

void Sort::MergePass(int h) 
{
	int i = 0;
	while (i + 2 * h <= length)           //待归并记录有两个长度为h的子序列
	{
		Merge(i, i+h-1, i+2*h-1);
		i = i + 2 * h;
	}
	if (i + h < length) 
		Merge(i, i+h-1, length-1);    //两个子序列一个长度小于h
}

void Sort::MergeSort2( )      
{
	int h = 1;                            //初始时子序列长度为1
	while (h < length)
	{
		MergePass(h);                     //一趟归并排序
		h = 2 * h;
	}
}

void Sort::SelectSort( )       
{   
	int i, j, index, temp;
	for (i = 0; i < length - 1; i++)  	        //进行length-1趟简单选择排序
	{  
		index = i; 		
		for (j = i + 1; j < length; j++)         //在无序区中选取最小记录
			if (data[j] < data[index]) index = j;
		if (index != i) {
			temp = data[i]; data[i] = data[index]; data[index] = temp;
		}
	}
}

void Sort::Sift(int k, int last)        
{
  	int i, j, temp;
  	i = k; j =2 * i + 1;                // i是被筛选结点,j是i的左孩子
  	while (j <= last)                  //筛选还没有进行到叶子
  	{
    	if (j < last && data[j] < data[j+1]) j++;     // j指向左右孩子的较大者
		if (data[i] > data[j]) 
			break;               //已经是堆
		else 
		{
  			temp = data[i]; data[i] = data[j]; data[j] = temp;   
  			i = j; j = 2 * i + 1;                //被筛结点位于原来结点j的位置
		}
  	}
}

void Sort::HeapSort( )     
{
  	int i, temp;
  	for (i = ceil(length/2) - 1; i >= 0; i--)       //从最后一个分支结点至根结点
		Sift(i, length-1) ;     
  	for (i = 1; i < length; i++)         
  	{
    	temp = data[0]; data[0] = data[length-i]; data[length-i] = temp; 
		Sift(0, length-i-1);                          //重建堆
  	}
}

void Sort::Merge(int first1, int last1, int last2) 
{
	int *temp = new int[length];           //数组temp作为合并的辅助空间
	int i = first1, j = last1 + 1, k = first1;
	while (i <= last1 && j <= last2)
	{   
		if (data[i] <= data[j]) 
			temp[k++] = data[i++];    //取较小者放入temp[k]
		else 
			temp[k++] = data[j++]; 
	}
	while (i <= last1)                  //对第一个子序列进行收尾处理
		temp[k++] = data[i++]; 
	while (j <= last2)                  //对第二个子序列进行收尾处理
		temp[k++] = data[j++];  
	for (i = first1; i <= last2; i++)         //将合并结果传回数组r
	    data[i] = temp[i];
	delete[ ] temp;
}

void Sort::MergeSort1(int first, int last)
{ 
	if (first == last) 
  		return;        //待排序序列只有1个记录,递归结束
  	else {
		int mid = (first + last)/2;
		MergeSort1(first, mid);          //归并排序前半个子序列
		MergeSort1(mid+1, last);        //归并排序后半个子序列
		Merge(first, mid, last);            //将两个已排序的子序列合并
	}
}

void Sort::ShellSort( )        
{	
	int temp, d, i, j;
	for (d = length/2; d >= 1; d = d/2)         //增量为d进行直接插入排序
	{
		for (i = d; i < length; i++)               //进行一趟希尔排序
		{
			temp = data[i];                    //暂存待插入记录
			for (j = i - d; j >= 0 && temp < data[j]; j = j - d)
				data[j + d] = data[j];                //记录后移d个位置
			data[j + d] = temp;
		}
	}
}

Sort :: Sort(int r[ ], int n)
{
  	data = new int[n];
  	for (int i = 0; i < n; i++)
    	data[i] = r[i];
  	length = n;
}

Sort :: ~Sort( )
{
  	delete[ ] data;
}

void Sort :: Print( )
{
  	for (int i = 0; i < length; i++)
    	cout << data[i] << "\t";
}

int Sort::Partition(int first, int last)
{	
	int i = first, j = last, temp;              //初始化一次划分的区间
	while (i < j)	
	{
		while (i < j && data[i] <= data[j]) j--;      //右侧扫描
		if (i < j) { 
			temp = data[i];	data[i] = data[j]; data[j] = temp; 
			i++; 
		}
		while (i < j && data[i] <= data[j]) 
			i++;     //左侧扫描
		if (i < j) {
			temp = data[i]; data[i] = data[j]; data[j] = temp;  
			j--; 
		}
	}
	return i;                           // i为轴值记录的最终位置
}

void Sort::QuickSort(int first, int last)
{	
  	if (first >= last) 
  		return;                            //区间长度为1,递归结束
  	else 
  	{
		int pivot = Partition(first, last);     //一次划分
		QuickSort(first, pivot-1);         //对左侧子序列进行快速排序
		QuickSort(pivot+1, last);         //对右侧子序列进行快速排序
	}
}

int main( )
{
	int select, r[10] = {2, 5, 7, 1, 9, 4, 3, 6, 5, 8};
  	cout << "原数据是:";
  	for(int i = 0; i < 10; i ++ )
  		cout << r[i] << " ";
  	cout << endl;
  	Sort L(r, 10);
  	cout << "1. 直接插入排序      2. 希尔排序" << endl;
  	cout << "3. 起泡排序          4. 快速排序" << endl;
  	cout << "5. 简单选择排序      6. 堆排序" << endl;
  	cout << "7. 二路归并递归排序  8. 二路归并非递归排序" << endl;
  	cout << "请输入使用的排序技术编号:" ;
  	cin >> select;
  	switch (select)
  	{
    	case 1: L.InsertSort( ); break;     
		case 2: L.ShellSort( ); break;
		case 3: L.BubbleSort( ); break;      
		case 4: L.QuickSort(0, 9); break;
		case 5: L.SelectSort( ); break;       
		case 6: L.HeapSort( ); break;
		case 7: L.MergeSort1(0, 9); break;  
		case 8: L.MergeSort2( ); break;
		default : cout << "输入排序编号错误" << endl; break;
  	}
	L.Print( );
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值