zoukankan      html  css  js  c++  java
  • 插入排序、冒泡排序、选择排序、希尔排序、高速排序、归并排序、堆排序和LST基数排序——C++实现

    首先是算法实现文件Sort.h。代码例如以下:

    <pre name="code" class="java">/*
    * 实现了八个经常使用的排序算法:插入排序、冒泡排序、选择排序、希尔排序
    * 以及高速排序、归并排序、堆排序和LST基数排序
    * @author gkh178
    */
    #include <iostream>
    
    template<class T>
    void swap_value(T &a, T &b)
    {
    	T temp = a;
    	a = b;
    	b = temp;
    }
    
    //插入排序:时间复杂度o(n^2)
    template<class T>
    void insert_sort(T a[], int n)
    {
    	for (int i = 1; i < n; ++i)
    	{
    		T temp = a[i];
    		int j = i - 1;
    		while (j >= 0 && a[j] > temp)
    		{
    			a[j + 1] = a[j];
    			--j;
    		}
    		a[j + 1] = temp;
    	}
    }
    
    //冒泡排序:时间复杂度o(n^2) 
    template<class T>
    void bubble_sort(T a[], int n)
    {
    	for (int i = n - 1; i > 0; --i)
    	{
    		for (int j = 0; j < i; ++j)
    		{
    			if (a[j] > a[j + 1])
    			{
    				swap_value(a[j], a[j + 1]);
    			}
    		}
    	}
    }
    
    //选择排序:时间复杂度o(n^2)
    template<class T>
    void select_sort(T a[], int n)
    {
    	for (int i = 0; i < n - 1; ++i)
    	{
    		T min = a[i];
    		int index = i;
    		for (int j = i + 1; j < n; ++j)
    		{
    			if (a[j] < min)
    			{
    				min = a[j];
    				index = j;
    			}
    		}
    		a[index] = a[i];
    		a[i] = min;
    	}
    }
    
    //希尔排序:时间复杂度介于o(n^2)和o(nlgn)之间 
    template<class T>
    void shell_sort(T a[], int n)
    {
    	for (int gap = n / 2; gap >= 1; gap /= 2)
    	{
    		for (int i = gap; i < n; ++i)
    		{
    			T temp = a[i];
    			int j = i - gap;
    			while (j >= 0 && a[j] > temp)
    			{
    				a[j + gap] = a[j];
    				j -= gap;
    			}
    			a[j + gap] = temp;
    		}
    	}
    }
    
    //高速排序:时间复杂度o(nlgn)  
    template<class T>
    void quick_sort(T a[], int n)
    {
    	_quick_sort(a, 0, n - 1);
    }
    template<class T>
    void _quick_sort(T a[], int left, int right)
    {
    	if (left < right)
    	{
    		int q = _partition(a, left, right);//一次划分得到的中位数的位置
    		_quick_sort(a, left, q - 1);//对左边进行递归快排
    		_quick_sort(a, q + 1, right);//对右边进行递归快排
    	}
    }
    template<class T>
    int _partition(T a[], int left, int right)
    {
    	T pivot = a[left];//设置第一个数为中位数
    	while (left < right)
    	{
    		while (left < right && a[right] >= pivot)
    		{
    			--right;
    		}
    		a[left] = a[right];//从右到左寻找一个比中位数小的数。将其填入中位数的所在位置
    		while (left < right && a[left] <= pivot)
    		{
    			++left;
    		}
    		a[right] = a[left];//从左到右寻找一个比中位数大的数,将其填入刚才空缺的位置
    	}
    	a[left] = pivot;//将中位数填入空缺位置
    	return left;
    }
    
    //归并排序:时间复杂度o(nlgn)  
    template<class T>
    void merge_sort(T a[], int n)
    {
    	_merge_sort(a, 0, n - 1);
    }
    template<class T>
    void _merge_sort(T a[], int left, int right)
    {
    	if (left < right)
    	{
    		int mid = left + (right - left) / 2;
    		_merge_sort(a, left, mid);//对左边递归归并排序
    		_merge_sort(a, mid + 1, right);//对右边递归归并排序
    		_merge(a, left, mid, right);//将左右归并起来
    	}
    }
    template<class T>
    void _merge(T a[], int left, int mid, int right)
    {
    	int length = right - left + 1;
    	T *newA = new T[length];//用来暂存原始数组
    	for (int i = 0, j = left; i <= length - 1; ++i, ++j)
    	{
    		*(newA + i) = a[j];
    	}
    	int i = 0;
    	int j = mid - left + 1;
    	int k = left;
    	for (; i <= mid - left && j <= length - 1; ++k)
    	{
    		if (*(newA + i) < *(newA + j))
    		{
    			a[k] = *(newA + i);
    			++i;
    		}
    		else
    		{
    			a[k] = *(newA + j);
    			++j;
    		}
    	}
    	//将左边或者右边多余的数填入数组
    	while (i <= mid - left)
    	{
    		a[k++] = *(newA + i);
    		++i;
    	}
    	while (j <= right - left)
    	{
    		a[k++] = *(newA + j);
    		++j;
    	}
    	delete[] newA;
    }
    
    //堆排序:时间复杂度o(nlgn) 
    template<class T>
    void heap_sort(T a[], int n)
    {
    	built_max_heap(a, n);//建立初始大根堆  
    	//交换首尾元素。并对交换后排除尾元素的数组进行一次上调整  
    	for (int i = n - 1; i >= 1; --i)
    	{
    		swap_value(a[0], a[i]);
    		up_adjust(a, i);
    	}
    }
    //建立一个长度为n的大根堆  
    template<class T>
    void built_max_heap(T a[], int n)
    {
    	up_adjust(a, n);
    }
    //对长度为n的数组进行一次上调整  
    template<class T>
    void up_adjust(T a[], int n)
    {
    	//对每一个带有子女节点的元素遍历处理,从后到根节点位置  
    	for (int i = n / 2; i >= 1; --i)
    	{
    		adjust_node(a, n, i);
    	}
    }
    //调整序号为i的节点的值  
    template<class T>
    void adjust_node(T a[], int n, int i)
    {
    	//节点有左右孩子  
    	if (2 * i + 1 <= n)
    	{
    		//右孩子的值大于节点的值,交换它们  
    		if (a[2 * i] > a[i - 1])
    		{
    			swap_value(a[2 * i], a[i - 1]);
    		}
    		//左孩子的值大于节点的值。交换它们  
    		if (a[2 * i - 1] > a[i - 1])
    		{
    			swap_value(a[2 * i - 1], a[i - 1]);
    		}
    		//对节点的左右孩子的根节点进行调整  
    		adjust_node(a, n, 2 * i);
    		adjust_node(a, n, 2 * i + 1);
    	}
    	//节点仅仅有左孩子,为最后一个有左右孩子的节点  
    	else if (2 * i == n)
    	{
    		//左孩子的值大于节点的值,交换它们  
    		if (a[2 * i - 1] > a[i - 1])
    		{
    			swap_value(a[2 * i - 1], a[i - 1]);
    		}
    	}
    }
    
    //基数排序的时间复杂度为o(distance(n+radix)),distance为位数。n为数组个数,radix为基数  
    //本方法是用LST方法进行基数排序。MST方法不包括在内  
    //当中參数radix为基数,一般为10。distance表示待排序的数组的数字最长的位数。n为数组的长度 
    template<class T>
    void lst_radix_sort(T a[], int n, int radix, int distance)
    {
    	T* newA = new T[n];//用于暂存数组  
    	int* count = new int[radix];//用于计数排序。保存的是当前位的值为0 到 radix-1的元素出现的的个数  
    	int divide = 1;
    	//从倒数第一位处理到第一位  
    	for (int i = 0; i < distance; ++i)
    	{
    		//待排数组复制到newA数组中
    		for (int j = 0; j < n; ++j)
    		{
    			*(newA + j) = a[j];
    		}
    		//将计数数组置0  
    		for (int j = 0; j < radix; ++j)
    		{
    			*(count + j) = 0;
    		}
    		for (int j = 0; j < n; ++j)
    		{
    			int radixKey = (*(newA + j) / divide) % radix; //得到数组元素的当前处理位的值  
    			(*(count + radixKey))++;
    		}
    		//此时count[]中每一个元素保存的是radixKey位出现的次数  
    		//计算每一个radixKey在数组中的结束位置。位置序号范围为1-n  
    		for (int j = 1; j < radix; ++j)
    		{
    			*(count + j) = *(count + j) + *(count + j - 1);
    		}
    		//运用计数排序的原理实现一次排序,排序后的数组输出到a[]  
    		for (int j = n - 1; j >= 0; --j)
    		{
    			int radixKey = (*(newA + j) / divide) % radix;
    			a[*(count + radixKey) - 1] = newA[j];
    			--(*(count + radixKey));
    		}
    		divide = divide * radix;
    	}
    	delete[] newA;
    	delete[] count;
    }


    
    
    然后是測试文件main.cpp。代码例如以下:

    #include "Sort.h"
    using namespace std;
    
    template<class T>
    void printArray(T a[], int n)
    {
    	for (int i = 0; i < n; ++i)
    	{
    		cout << a[i] << " ";
    	}
    	cout << endl;
    }
    
    int main()
    {
    	for (int i = 1; i <= 8; ++i)
    	{
    		int arr[] = { 45, 38, 26, 77, 128, 38, 25, 444, 61, 153, 9999, 1012, 43, 128 };
    		switch (i)
    		{
    		case 1:
    			insert_sort(arr, sizeof(arr) / sizeof(arr[0]));
    			break;
    		case 2:
    			bubble_sort(arr, sizeof(arr) / sizeof(arr[0]));
    			break;
    		case 3:
    			select_sort(arr, sizeof(arr) / sizeof(arr[0]));
    			break;
    		case 4:
    			shell_sort(arr, sizeof(arr) / sizeof(arr[0]));
    			break;
    		case 5:
    			quick_sort(arr, sizeof(arr) / sizeof(arr[0]));
    			break;
    		case 6:
    			merge_sort(arr, sizeof(arr) / sizeof(arr[0]));
    			break;
    		case 7:
    			heap_sort(arr, sizeof(arr) / sizeof(arr[0]));
    			break;
    		case 8:
    			lst_radix_sort(arr, sizeof(arr) / sizeof(arr[0]), 10, 4);
    			break;
    		default:
    			break;
    		}
    		printArray(arr, sizeof(arr) / sizeof(arr[0]));
    	}
    	return 0;
    }

    最后是执行结果图,例如以下:



  • 相关阅读:
    haproxy 2.5 发布
    cube.js sql 支持简单说明
    基于graalvm 开发一个cube.js jdbc driver 的思路
    apache kyuubi Frontend 支持mysql 协议
    oceanbase 资源池删除说明
    基于obd 的oceanbase 扩容说明
    jfilter一个方便的spring rest 响应过滤扩展
    cube.js schema 定义多datasource 说明
    typescript 编写自定义定义文件
    meow 辅助开发cli 应用的工具
  • 原文地址:https://www.cnblogs.com/yfceshi/p/6956520.html
Copyright © 2011-2022 走看看