基本排序算法总结(C/C++)

基本排序算法分为五类:
①交换排序(冒泡排序、快速排序)
②插入排序(直接插入排序、Shell排序)
③基数排序
④归并排序
⑤堆排序(简单选择排序、堆排序)

下面直接上代码:

#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;


/*
	*********************************************** Insert Sort ************************************************
*/

/*
*********** 0(n2) *************
主要思想:
逐个将无序区的元素插入到有序区,单个元素是有序的。
*/
void DirectInsertSort(int arr[], int length)
{	
	int tmp;
	int index;
	for (int i = 1; i < length; ++i)
	{
		if (arr[i] < arr[i - 1])
		{
			tmp = arr[i];
			index = i;
			while (index > 0 && arr[index - 1] > tmp)
			{
				arr[index] = arr[index - 1];
				--index;
			}
			arr[index] = tmp;
		}
	}
}

/*
******** nlog(n) < X < O(n2) ************
主要思想:
改进的直接插入排序,依据一组距离向量来确定哪两个元素比较,进而排序。如一组向量为{5,3,1};
*/
void ShellSort(int arr[], int length, int dk)
{
	int tmp;
	int index;
	for (int i = 0; i < length - dk; ++i)
	{
		if (arr[i] > arr[i + dk])
		{
			tmp = arr[i + dk];
			index = i;
			while (index >= 0 && arr[index] > tmp)
			{
				arr[index + dk] = arr[index];
				index -= dk;
			}
			arr[index + dk] = tmp;
		}
	}
}

/*
	********************************************** Exchange Sort ************************************************
*/

/*
********** X <= O(n2) ***********
主要思想:
这个一个改进的冒泡排序,原始需要O(n2)时间复杂度,原因是原始的排序不是基于相邻元素的比较,所以没一趟仅知道有序区增加一个元素,其它区域的信息依然不知。
以下基于相邻元素的比较,可以确定更多有序区的范围,从而减少趟数,减少时间开销。
*/
void AdvancedBubleSort(int arr[], int length)
{
	int tmp = 0;
	int index = 0;
	for (int i = length - 1; i > 0; --i)
	{
		for (int j = 0; j < i; ++j)
		{
			if (arr[j] > arr[j + 1])
			{
				index = j + 1;
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
		i = index;
		index = 0;
	}
}

/*
*************O(nlogn) < X < O(n2)*****************
主要思想:
类似二分查找,每次算法都希望将无序数组均分为两个大概相等的子数组,以此递归。
但有可能不理想,会造成和冒泡一样的开销(发生在:每次取到的哨兵元素都是边缘元素)。
*/

int SubFastSort(int arr[], int low, int high)
{
	int middle = arr[low];
	while (low < high)
	{
		while (low < high && arr[high] > middle) high--;
		if (low == high)
			break;
		arr[low++] = arr[high];

		while (low < high && arr[low] < middle) low++;
		if (low == high)
			break;
		arr[high--] = arr[low];
	}
	arr[low] = middle;
	return low;
}

void FastSort(int arr[], int low, int high)
{
	if (low >= high)
		return;
	int middle = SubFastSort(arr, low, high);
	FastSort(arr, low, middle-1);
	FastSort(arr, middle+1, high);
}

/*
	********************************************** Merging Sort ***************************************************
*/
/*
**************O(nlogn)**************
主要思想:
每次将数组一分为二递归下去,知道子数组元素个数为1,则有序了。
回调过程进行合并。
*/
void MergeArray(int s[], int t[], int low, int middle, int high)
{
	int t_index = low;
	int s_low = low;
	int s_middle = middle + 1;
	for ( ; s_low <= middle && s_middle <= high ; )
	{
		if (s[s_low] < s[s_middle])
			t[t_index++] = s[s_low++];
		else	t[t_index++] = s[s_middle++];
	}

	while (s_low <= middle) t[t_index++] = s[s_low++];
	while (s_middle <= high) t[t_index++] = s[s_middle++];
}
 
void SubMergingSort(int s[], int t[], int i, int low, int high)
{
	if (low == high)
	{
		if (1 == i%2) t[low] = s[low];
	}
	else
	{
		int middle = ((high - low) >> 2) + low; //(low + high)/2;
		SubMergingSort(s, t, i+1, low, middle);
		SubMergingSort(s, t, i+1, middle+1, high);
		if (1 == i%2)
			MergeArray(s, t, low, middle, high);
		else	
			MergeArray(t, s, low, middle, high);
	}
}

void MergingSort(int arr[], int length)
{
	int *p = nullptr;
	p = (int *)malloc(sizeof(int)*length);
	if (p)
	{
		SubMergingSort(arr, p, 0, 0, length-1);
		free(p);
	}
}

/*
	************************************************ Heap Sort ********************************************************
*/
/*
*************O(n2)*****************
主要思想:
找到要找的元素才进行交换,减少了交换的次数。
*/

void SimpleSelectSort(int arr[], int length)
{
	int min;
	for (int i = 0; i < length; ++i)
	{
		min = i;
		for (int j = i+1; j < length; ++j)
		{
			if (arr[i] > arr[j])
			{
				min = j;
			}
		}
		if (min != i)
		{
			arr[min] = arr[min] ^ arr[i];
			arr[i] = arr[min] ^ arr[i];
			arr[min] = arr[min] ^ arr[i];
		}

	}
}

/*
************O(nlogn)***************
主要思想:
第一步:
利用数组索引,构建大堆项(排序结果是升序)或者小堆项(排序结果是降序)。
第二步:
交换头尾元素,数组长度变量减1,再构建成大/小堆项,再回到第一步
*/
void ShiftDown(int arr[], int length, int pos)
{
    int left, right;
    while (pos <= length/2-1)
    {
        left = pos*2+1;
        right = pos*2+2;
        if (right < length)
        {
            if (arr[left] < arr[right])
                left = right;
        }
        if (arr[left] > arr[pos])
        {
            arr[left] = arr[left] ^ arr[pos];
            arr[pos] = arr[left] ^ arr[pos];
            arr[left] = arr[left] ^ arr[pos];
            pos = left;
        }    
        else break;        
    }
}

void MakeBigHeap(int arr[], int length)
{
    int left;
    int right;
    for (int i = length/2 - 1; i >= 0; --i)
    {
        ShiftDown(arr, length, i);
    }
}

void HeapSort(int arr[], int length)
{
    if (length <= 1)
        return ;
    MakeBigHeap(arr, length);

    int index = length-1;
    int left, right;
    while (index > 0)
    {
        swap(arr[0], arr[index--]);
        ShiftDown(arr, index+1, 0); // 保持大堆性质
    }
}

int main(int argc, char *argv[])
{
	int arr[] = {9,5,6,4,8,7,3,1,2,0};
	DirectInsertSort(arr, 10);

	int dk[] = {5,3,1};
	int arr1[] = {9,5,6,4,8,7,3,1,2,0};
	for (int i = 0; i < sizeof(dk)/sizeof(int); ++i)
	{
		ShellSort(arr1, 10, dk[i]);
	}

	int arr2[] = {9,5,6,4,8,7,3,1,2,0};
	AdvancedBubleSort(arr2, 10);

	int arr3[] = {1,2,8,3,4,5,7,6,9,0};
	MergingSort(arr3, 10);

	int arr4[] = {1,2,8,3,4,5,7,6,9,0};
	FastSort(arr4, 0, 9);

	int arr5[] = {1,2,8,3,4,5,7,6,9,0};
	SimpleSelectSort(arr5, 10);

	int arr6[] = {1,2,8,3,4,5,7,6,9,0};
	HeapSort(arr6, 10);

	ostream_iterator<int> os_iter(cout, " ");
	copy(begin(arr), end(arr), os_iter);
	endl(cout);
	copy(begin(arr1), end(arr1), os_iter);
	endl(cout);
	copy(begin(arr2), end(arr2), os_iter);
	endl(cout);
	copy(begin(arr3), end(arr3), os_iter);
	endl(cout);
	copy(begin(arr4), end(arr4), os_iter);
	endl(cout);
	copy(begin(arr5), end(arr5), os_iter);
	endl(cout);
	copy(begin(arr6), end(arr6), os_iter);
	endl(cout);

	return 0;
}



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值