简单回顾一下十大排序算法

十大排序算法可以分为比较类和非比较类排序:

排序对比表
类型排序方式算法名称

平均

时间复杂度

最差

时间复杂度

最好

时间复杂度

空间复杂度

稳定性
比较类型交换式冒泡排序O(n²)O(n²)O(n)O(1)稳定
比较类型交换式快速排序O(nlog₂n)O(n²)O(nlog₂n)O(nlog₂n)(递归式)不稳定
比较类型

插入式

插入排序O(n²)O(n²)O(n²)O(1)稳定
比较类型插入式希尔排序O(nlog₂n)O(n²)O(n)O(1)不稳定
比较类型选择式选择排序O(n²)O(n²)O(n²)O(1)不稳定
比较类型选择式堆排序O(nlog₂n)O(nlog₂n)O(nlog₂n)O(1)不稳定
比较类型拉链式插入归并排序O(nlog₂n)O(nlog₂n)O(nlog₂n)O(n)稳定
非比较类型数组计数计数排序O(n)O(n)O(n)O(n)稳定
非比较类型分桶式桶排序O(n)O(n²)O(n)O(n)稳定
非比较类型按位数排序基数排序O(n)O(n)O(n)O(n)稳定

 

参考链接:https://www.cnblogs.com/onepixel/articles/7674659.html

P1.h

#pragma once
#include <iostream>

#include <list>
#include <vector>
using namespace std;
//参考链接https://www.cnblogs.com/onepixel/articles/7674659.html

class P1
{
public:
	P1();
	P1(int *p, int size);
	~P1();

	//交换排序,插入排序,选择排序,归并排序,都是建立在比较的基础上的排序

	/*交换排序*/
	void swap_bubbleSort();
	void swap_quickSort();
	void swap_quickSort(int left,int right);
	void swap_quickSort1();//非递归
	/*插入排序*/
	void insert_simpleInsertSort();
	void insert_shellSort();

	/*选择排序*/
	void choicSort();
	void heapSort();
	void makeMaxHeap(int star,int end);

	/*归并排序*/
	void megreSort();
	list<int> megreSort_2(list<int>& listAy);
 
	//计数排序,桶排序,基数排序,都是建立在非比较的基础上的排序
	
	/*计数排序*/
	void countSort();
	/*桶排序*/
	void bucketSort();	
	/*基数排序*/
	void orderSort();	

	void randomSort();
	void printfData();
private:
	int* m_array;
	int  m_size;

};

P1.cpp

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

#include <list>
#include <vector>
using namespace std;


P1::P1()
{
}

P1::P1(int *p,int size)
{
	m_array = p;
	m_size = size;
}


P1::~P1()
{
}


/*冒泡排序*/
void P1::swap_bubbleSort()
{
	randomSort();
	//排序前
	cout << "初始排序:" << endl;
	printfData();

	for (size_t i = 0; i < m_size; i++)
	{
		//依次和相邻元素比对,把大的往后面挪动,每执行一次,最大就会在最后,也就是说,m_size-1-i后面的都是拍好序的
		
		for (size_t j = 0; j < m_size-i-1;j++)
		{
			if (m_array[j] > m_array[j+1])
			{
				int temp = m_array[j];
				m_array[j] = m_array[j+1];
				m_array[j+1] = temp;
			}
		}
		cout<<"第"<<i+1<<"次循环"<<endl;
		printfData();
	}

	/*
	采用了双重for循环,时间负责度为O(n²)
	并且在算法中并未开辟新的内存*,空间复杂度为O(1)
	这是最简单的排序算法
	*/
}

void P1::swap_quickSort()
{
	/* 
	快速排序的算法分为三步
	第一步,先选出标量,用下标0的位置元素的为标量值,在标量后面查找小于标量数值的个数,并将每个小于他的数值依次排在标量后面的N个下标里。
	第二步,将标量与排在他后面的最后一个小于他的值的位置交换。这样就实现了,将标量插入在大于和小于他本身之间,将数字分为两个区域,一个是大于标量,一个是小于标量
	第三步,将标量所在的位置下标,重新计算出新的两个分治起始范围,使用递归计算结果。
	*/
	int left = 0;
	int right = m_size-1;
	randomSort();
	cout<<"快速排序开始前"<<endl;
	printfData();
	swap_quickSort(left,right);
	cout << "快速排序结束" << endl;
	printfData();

	/*
	单重for循环加递归,其实理论上来说是N次+两个递归,每个递归里面有有两次O(N),
	也就是T(n) = 2T(n/2) + O(n),想看证明的参考这个链接
	所有的执行次数加在一块,最坏是无限趋近于O(n²)的
	https://blog.csdn.net/oohaha_123/article/details/26558363?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param
	
	在算法中使用了递归,递归的函数没执行完,不会释放函数的内存,也就是函数本身存在堆中,需要在函数执行完才释放内存,所以开辟递归函数的次数
	空间复杂度为O(log2n),最坏就是O(n)
	这是最简单的排序算法
	*/
}

void P1::swap_quickSort(int left,int right)
{
	int piovt = left;
	int  index = piovt + 1;
	if (left < right)
	{
		cout << " 开始时left = " << left << "right=" << right << endl;
 		printfData();
		cout << endl;
		//找出后面比piovt一小的元素,并将它放在我后面
		for (size_t i = index; i <= right; i++)
		{
			//如果i位置比piovt的元素小,将元素i与 index位置的元素交换,index++,也就是说,本for循环结束,就会把大于标量和小于标量的值分成两份。
			if (m_array[i] < m_array[piovt])
			{
				int temp = m_array[i];
				m_array[i] = m_array[index];
				m_array[index] = temp;
				index++;
			}
			cout << "本次标量已将,大小区分开" << endl;
			printfData();
		}
		/*
		以上部分略有难懂的地方,举例说明比较贴切。
		如 10,8,19,9,16。执行一次交换之后的排列是
		10,8,9,19,16
		index执行了两次++,index =3,因为标量是10,10后面有两个比他小的值,index初始值=1,执行两次++后值是3。
		*/
		cout << endl;
	
		/*
		for结束就会计算标量应该在的位置,交换开始前,是在起始位置。
		交换后可将大于与小于的分开,也就是将标量与最后一个小于他的值的位置交换一下。
		*/

		index -= 1;//标量应该在的位置就是2,就是9所在的位置下标。
		int temp = m_array[index];
		m_array[index] = m_array[piovt];
		m_array[piovt] = temp;

		cout << "本次左右起始,交换完成" << endl;
		printfData();
		cout <<  endl;

		swap_quickSort(index+1, right);
		swap_quickSort(left,index-1);
	}
}

void P1::swap_quickSort1()
{
	/*
	快速排序的非递归,思想是把每次的其实和结束存到堆栈中,先进后出,后进先出的方式,存取,左右的值。
	第一次先存入两对left,right
	只要堆栈中大于0,即可取出一对数值重新计算,新的left right,知道堆栈中为空。
	采用list,并从back处取出数据,取出后,pop,丢掉使用过的数据。
	*/
	int left = 0;
	int right = m_size - 1;
	int piovt = left;
	int  index = piovt + 1;
	if (left < right)
	{
		cout << " 开始时left = " << left << "right=" << right << endl;
		printfData();
		cout << endl;
		for (size_t i = index; i <= right; i++)
		{
			if (m_array[i] < m_array[piovt])
			{
				int temp = m_array[i];
				m_array[i] = m_array[index];
				m_array[index] = temp;
				index++;
			}

		}
		index -= 1;
		int temp = m_array[index];
		m_array[index] = m_array[piovt];
		m_array[piovt] = temp;

		list<pair<int, int>*> leftRight;
		leftRight.push_back(new pair<int,int>(left,index-1));
		leftRight.push_back(new pair<int, int>(index+1, right));

		while (leftRight.size() > 0)
		{
			left = leftRight.back()->first;
			right = leftRight.back()->second;
			leftRight.pop_back();
			piovt = left;
			index = piovt + 1;
			if (left < right)
			{
				//找出后面比piovt一小的元素,并将它放在我后面
				for (size_t i = index; i <= right; i++)
				{
					//如果i位置比piovt的元素小,将元素i与 index位置的元素交换,index++,也就是说,本for循环结束,就会把大于标量和小于标量的值分成两份。
					if (m_array[i] < m_array[piovt])
					{
						int temp = m_array[i];
						m_array[i] = m_array[index];
						m_array[index] = temp;
						index++;
					}
				}
				index -= 1;
				int temp = m_array[index];
				m_array[index] = m_array[piovt];
				m_array[piovt] = temp;

				leftRight.push_back(new pair<int, int>(left, index - 1));
				leftRight.push_back(new pair<int, int>(index + 1, right));
			}
		}
		cout << " 结束时:"<< endl;
		printfData();
	}

}

/*插入排序*/
void P1::insert_simpleInsertSort()
{
	/*
	插入排序原理:默认前面的数字都是排好序的,使用for循环,依次查找后面每个元素在前面排好序的位置。
	不过这个过程有两个重要的步骤。
	第一步,先将需要确定位置的数字使用临时变量存储。
	第二步,从这个变量依次向前倒叙查找,每找到比自己大的元素,就将这个大的元素后移一个位置。
	第三步,确定当前数字的位置后,直接插入

	示例,3,2,1,0
	
	第一次默认3是排好序的,从2开始向前查找2在 【3】 中的位置,第一次对比,就将3放到了下标1的位置上
	插入后前两个数字【2,3】是排好顺序的

	第二次,过程是【2,3,3】,【2,2,3】,最后将1放在起始位置后是【1,2,3】

	第三次,过程是【1,2,3,3】,【1,2,2,3】,【1,1,2,3】,最后是【0,1,2,3】
	*/
	cout << " 开始时:" << endl;
	printfData();
	for (size_t i = 1; i != m_size; ++i)
	{
		int index = i - 1;
		int current = m_array[i];
		while (index>=0)
		{
			if (m_array[index] > current)
			{
				m_array[index + 1] = m_array[index];
				index--;
			}
			else
			{
				break;
			}
		}
		m_array[index + 1] = current;
		cout << " 循环一次" << endl;
		printfData();
	}
	cout << endl;
	cout << " 结束时:" << endl;
	printfData();


	/*
	时间复杂度为O(n²)
	空间复杂度为O(1)
	*/
}

void P1::insert_shellSort()
{
	/*
	希尔排序的过程是从插入排序的基础上改进的,也是时间复杂度第一个突破O(n²)的排序算法
	明白了插入排序的原理,再来理解希尔排序其实是很好理解的。
	希尔排序和插入排序的不同在于分组,即按照M个元素间隔成一组。每次会在每个组中查找最小的元素并将它放置在最前,且找到大的就往后放。

	如【7,8,9,6,3,2,1,0】

	第一次排序从,下标4开始依次向后,每次是与 减去4(分组的长度)的元素比较,即
	4与0比较如果下标4的比下标0的元素小,就会交换位置。
	5与1比较
	6与2比较
	7与3比较
	第一次执行完的效果是
	3,2,1,0,7,8,9,6


	第二次执行分组长度变成2,
	那就会是
	从2下标开始依次向后,每次是与减去2的元素比较,即
	2与0;
	1,2,3,0,7,8,9,6
	3与1
	1,0,3,2,7,8,9,6
	4与2,4与0
	1,0,3,2,7,8,9,6
	5与3,3与1
	1,0,3,2,7,8,9,6
	6与4,4与2
	1,0,3,2,7,8,9,6
	7与5,5与3,3与1
	1,0,3,2,7,6,9,8

	第三次执行分组长度是1
	那就会是
	从1下标开始依次向后,每次是与减去2的元素比较,即
	1与0;
	1,2,3,0,7,8,9,6
	2与1,1与0;
	1,0,3,2,7,8,9,6
	4与3,3与2,2与1,1与0,

	依次类推
	*/

	cout << " 开始时:" << endl;
	printfData();
	 
	for (int gap =m_size/2; gap > 0; gap=gap/2)
	{
		for (size_t i= gap; i < m_size; ++i)
		{
			int current = m_array[i];
			int j = i;
			while (j-gap>=0 && m_array[j-gap]>current)
			{
				m_array[j] = m_array[j - gap];
				j = j - gap;
			}
			m_array[j] = current;
		}
		cout << " 分组数值为"<< gap <<"的比较结束:" << endl;
		printfData();

	}
	cout << endl;
	cout << " 结束时:" << endl;
	printfData();
}

/*选择排序*/
void P1::choicSort()
{
	randomSort();
	//排序前
	cout << "初始排序:" << endl;
	printfData();

	for (size_t i = 0; i < m_size; i++)
	{
		int curIndex = i;
		for (size_t j = i+1; j < m_size; j++)
		{
			if (m_array[j] < m_array[curIndex])
			{
				curIndex = j;
			}
		}
		int temp = m_array[i];
		m_array[i] = m_array[curIndex];
		m_array[curIndex] = temp;

		cout << "第" << i + 1 << "次循环" << endl;
		printfData();
	}



	/*
	选择排序和插入排序都是比较简单的排序算法,具体区别还是与的,冒泡是将最大的元素依次放在最后。
	插入排序则是,依次把最小的元素排在前面有序的最后,也就是从后面的元素中选出最小的元素,和当前元素交换位置。
	两者是时空复杂度是一样的。
	*/
}

void P1::heapSort()
{
	/*
	先构建一个大顶堆结构的数组排序,堆有点像是完全二叉树的结构。在数组中相关下标是有关系的,也就是说,如果根节点的下标是 i,
	那么他的左右子节点的下标就是:2*i+1和2*i+2,所以说,所有的叶子节点就是数组长度一半 +1开始的位置
	                                      0
									  /        \
									/            \
								   1               2
								 /    \          /    \
								3     4       5      6
     同样,当用数组构建这样一个结构的数据时,他的最左的非叶子节点的下标就是 n/2。
	 基于堆的结构:是要把最大的根节点的数值排列在第一个位置。相当于每调整一次大顶堆的结构,就会得到一个最大的值。而且和这个值是数组的第一个值。


	 根据这个规则,我们可以通过以下几步,来实现堆排序
	 第一步:先构建一个大顶堆结构的数组,将最大值排在第一个
	 第二步:倒序遍历数组,将大顶堆排序调整后的数值,依次与最后一个元素交换位置。
	 
	*/
	cout<<"堆排序:"<<endl;
	printfData();
	for (int i = m_size / 2 - 1; i >= 0; --i)
	{
		makeMaxHeap(i,m_size-1);
	}

	for (int i =m_size-1; i >= 0;--i)
	{
		int temp = m_array[i];
		m_array[i] = m_array[0];
		m_array[0] = temp;
		makeMaxHeap(0, i-1);
	}
	cout << "排序结束后:" << endl;
	printfData();
}
void P1::makeMaxHeap(int start, int end)
{
	/*
	采用,star-end之间的数构建大顶堆
	*/
	int dad = start;
	int sonLeft = 2 * dad + 1;


	while (sonLeft <= end)
	{
		int sonRight = sonLeft + 1;
		if (sonRight<=end && m_array[sonLeft] < m_array[sonRight])
		{
			sonLeft = sonRight;
		}
		if (m_array[dad] > m_array[sonLeft])
		{
			return;
		}
		else
		{
			int temp = m_array[dad];
			m_array[dad] = m_array[sonLeft];
			m_array[sonLeft] = temp;
			dad = sonLeft;
			sonLeft = 2 * dad + 1;


		}
	}

}

/*归并排序*/
void P1::megreSort()
{

	/*归并排序
	一开始一直想不通归并排序的道理。
	其实也很简单,为了实现从小到大的目的,将数分成两组,不停的分,直到分到每个组里边只有一个数。

	此时两组开始合并
	第一次合并肯定是,每个组只有一个数。

	遵循谁小谁先排队的规则,将小的排在前面,并从原来分组中删掉这个已经排好位置的数。
	形象的来说,两队小孩,依次从小到大排序。那么就从每队的第一个小孩开始比对,谁小谁就先去排队,并排在新队伍的后面。

	例如,一队小孩的身高为 2,5,6,10。另一队是,1,2,3,6。

	两队归并次序
	2与1比,1从原来队列删除,
	进入新的队列。


	此时三个队列的情况如下:
	2,5,6,9
	2,3,6
	新队列 1

	5,6,9
	2,3,6
	新队列 1,2

	5,6,9
	3,6
	新队列 1,2,2

	5,6,9
	6
	新队列 1,2,2,3

	6,9
	6
	新队列 1,2,2,3,5

	9
	6
	新队列 1,2,2,3,5,6

	9
	
	新队列 1,2,2,3,5,6,6


	新队列 1,2,2,3,5,6,9

	这句是归并后的结果。

	利用递归无限分组,分到不能分的时候,开始合并返回,依次回到上次函数的调用的地址,继续往下执行,最终就是排好顺序的结果
	*/
	cout << "归并开始:" << endl;
	printfData();
	list<int> list;
	for (int i = 0; i != m_size; ++i)
	{
		list.push_back(m_array[i]);
	}

	std::list<int> li = megreSort_2(list);
	
	int i = 0;
	std::list<int>::iterator iteStar = li.begin();
 
	for (std::list<int>::iterator iter = iteStar; iter!= li.end();++iter)
	{
		m_array[i] = *iter;
		++i;
	}
	cout << "归并结果:" << endl;
	printfData();

	/*
	归并排序时间复杂度是O(nlogn),T(n)=2T(n/2) +o(n),而且是非常稳定的,所以不存在最坏和最差的情况
	由于使用了递归和临时开辟的空间,所以空间复杂度是O(n)
	*/
}

list<int> P1::megreSort_2(list<int>& listAy)
{
	if (listAy.size() < 2)
	{
		return listAy;
	}

	list<int> leftAy;
	list<int> rightAy;

	int leftEnd = listAy.size() / 2;
	list<int>::iterator itEnd = listAy.begin();

	for (int i = 0; i != leftEnd; ++i)
	{
		itEnd++;
	}

	for (list<int>::iterator iter = listAy.begin(); iter!= itEnd;++iter)
	{
		leftAy.push_back(*iter);
	}
	for (list<int>::iterator iter = itEnd; iter != listAy.end(); ++iter)
	{
		rightAy.push_back(*iter);
	}

	list<int> newLeftAy = megreSort_2(leftAy);
	list<int> newRightAy = megreSort_2(rightAy);

	list<int> result;

	while (newLeftAy.size() > 0 && newRightAy.size() > 0)
	{
		if (newLeftAy.front()> newRightAy.front())
		{
			result.push_back(newRightAy.front());
			newRightAy.pop_front();
		}
		else
		{
			result.push_back(newLeftAy.front());
			newLeftAy.pop_front();
		}
	}
	
	while (newLeftAy.size() > 0)
	{
		result.push_back(newLeftAy.front());
		newLeftAy.pop_front();
	}
	while (newRightAy.size() > 0)
	{
		result.push_back(newRightAy.front());
		newRightAy.pop_front();
	}
	cout << "当前归并结果:" << endl;
	//printfData();

	for (std::list<int>::iterator iter = result.begin(); iter != result.end(); ++iter)
	{
		cout << *iter << ",";
	}
	cout << endl;
	return result;
}

//计数排序,桶排序,基数排序,都是建立在非比较的基础上的排序

/*计数排序*/
void P1::countSort()
{
	/*
	计数排序是最有趣的排序算法,理解起来很简单。因为是比较是整数数值,一般是需要大于0。

	算出这个里边最大数字是多少,创建一个这么长的数组,然后利用数值本身当做新数组的下标。并将数值存到这个新的数组中去。
	存几次其本身的数值加1,代表有几个这样的数字需要排序。
	存的过程,其实就是排序了,最终在新数组中,按照顺序输出,有些数字是多个,就需要多次打印。

	
	*/

	cout<<"计数排序前"<<endl;
	printfData();
	int maxValue = 0;

	for (int i = 0; i != m_size; ++i)
	{
		if (maxValue < m_array[i])
		{
			maxValue = m_array[i];
		}
	}
	const int size = maxValue + 1;
	int *pArray = new int[size]();

	for (int i = 0; i != m_size; ++i)
	{
		int value = m_array[i];
		pArray[value] += 1;//有多少个相同的数,这个下标就+多少次
	}

	//输出新数组的值即可
	int star = 0;
	for (int i = 0; i != size; ++i)
	{
		while (pArray[i] > 0)
		{
			int v = i;
			m_array[star] = v;
			star++;
			pArray[i]--;
		}
	}

	cout << "计数排序后" << endl;
	printfData();
}

/*桶排序*/
void P1::bucketSort()
{
	cout<<"桶排序的内部排序使用了 归并排序"<<endl;
	printfData();
	int min = 0;
	int max = 0;
	for (size_t i = 0; i < m_size; i++)
	{
		if (m_array[i] > max)
		{
			max = m_array[i];
		}
		if (m_array[i] < min)
		{
			min = m_array[i];
		}
	}
	int bucketsSize = 5;
	int bucketsCount = (max - min) / bucketsSize +1;
	vector<vector<int>> bucketVector(bucketsCount);

	for (int i = 0; i != m_size; ++i)
	{
		int index = (m_array[i]-min) / bucketsSize;
		bucketVector[index].push_back(m_array[i]);
	}
	int k = 0;
	for (int i = 0; i != bucketVector.size(); ++i)
	{
		list<int> allData;

		for (int j = 0; j != bucketVector[i].size(); ++j)
		{
			allData.push_back(bucketVector[i][j]);
		}
		allData = megreSort_2(allData);
		bucketVector[i].clear();

		for (list<int>::iterator iter = allData.begin(); iter != allData.end(); ++iter)
		{
			bucketVector[i].push_back(*iter);
			cout << *iter<<",";
			if (k < m_size)
			{
				m_array[k] = *iter;
			}
			k++;
		}
	}	

	cout<<"排序结束"<<endl;
	printfData();

	/*
	时间复杂度 和内部排序时采用的算法相关,也和桶的数量相关,最极限的情况下每个桶里边只有一个数,效率接近于计数排序。
	最差的情况下也是 O((n/m)*log(n/m)) m一般远小于n,所以可以忽略.
	空间复杂度为k*d,k为桶的个数,d为桶的空间,也就是O(n)
	*/
}

/*基数排序*/
void P1::orderSort()
{
	cout << "基数排序开始" << endl;
	printfData();
	int  max = 0;
	for (size_t i = 0; i < m_size; i++)
	{
		if (m_array[i] > max)
		{
			max = m_array[i];
		}
	}

	int  dCcount = 1;
	while (abs(max/10)>=1)
	{
		max = max / 10;
		dCcount++;
	}
	vector<vector<int>> buckets(10);
	int num = 1;
	int mod = 10;
	for (int i = 0; i != dCcount; ++i)
	{
		for (int j = 0; j != m_size; ++j)
		{
			//算出当前位数的值
			int v = ( m_array[j] % mod) / num;
			if (v < 0)
			{
				v = abs(v);
			}
			
			buckets[v].push_back(m_array[j]);
		}
		int index = 0;
		for (size_t n = 0; n < buckets.size(); n++)
		{
			for (int p = 0; p != buckets[n].size(); ++p)
			{
				m_array[index++] = buckets[n][p];
			}
			buckets[n].clear();
		}
	 
		num *= 10;
		mod *= 10;
	}

	//调整负数的顺序
	vector<int> negativeNumber;
	for (int n = m_size-1; n >=0; --n)
	{
		if (m_array[n] < 0)
		{
			negativeNumber.push_back(m_array[n]);
		}
	}
	for (int n =0;n!=m_size;++n)
	{
		if (m_array[n] >=0)
		{
			negativeNumber.push_back(m_array[n]);
		}
	}
	for (int n = 0;n!=m_size;++n)
	{
		m_array[n] = negativeNumber[n];
	}
	cout << "排序结束" << endl;
	printfData();

	/*
	时间复杂度为 O(d*2n + 2n),基本上还是线性的,d是最大位数,d远小于n
	空间复杂度为O(d+n)
	*/
}

void P1::randomSort()
{
	int randCount = rand() % 50;
	for (size_t j = 0; j != randCount; ++j) 
	{
		for (size_t i = 0; i < m_size; i++)
		{
			int swapIndex = rand() % m_size;
			int temp = m_array[i];
			m_array[i] = m_array[swapIndex];
			m_array[swapIndex] = temp;
		}
	}
	 
}

void P1::printfData()
{
	for (int i = 0; i != m_size; ++i)
	{
		cout << m_array[i] << ",";
	}
	cout << endl;
}

/*
排序总结,


冒泡排序,每次循环将最大的交换到最后的位置,内层for是 size - 1 - i结束
插入排序,每次循环将当前数与前面排好顺序的数比较,算出自己应该插入的位置,执行插入
选择排序,每次循环,从后面选出最小数的下标与当前位置的数交换
基数排序,按照个十百千万位进行 位数值排序,先按照个位排序,在按照百位排序,以此类推
桶排序,计算桶的设置桶的容量,计算最大数与最小数的差值,也就是计算一共多少个数,根据容量计算桶的个数。
分桶放置后,在桶内用归并或者快速排序。可以用来求第K小元素
计数排序,一般只能排列正数

快速排序,属于交换排序。每次循环是从自己后面的第一个数开始,遇到比自己小的就交换到当前位置,在算出自己的位置,与那最终的数交换
希尔排序,希尔排序是分组的插入排序,依次减少分组的大小,每次分组大小是原来的一半,初始分组大小是数组长度的一半,在分组内选择自己的位置
归并排序,归并排序是无限分组,每次从中间将数组分成左右两部分,直到长度为1,开始进行拉练式合并,那个组的第一个小,那个组先进入新的数组排序。
最后把剩余的全部放到新的组中,新的组中的数就是排好序的
堆排序,先构建一个大顶堆,父节点比子节点大,从最右侧的子节点开始构建,倒序构建。第一次构建后,最大的数就在0下标的位置。在利用for每次将最大的数放到最后。
重新构建一次大顶堆,结束后再次将最大的数排列在最后,每次构建堆的数组长度--
相对来说理解程度难一些。

*/
int main(int argc,char *argv[])
{
	int a[] = {10,11,12,13,43,45,21,3,4,5,1,2,4,0,123450,-100,-20};
	int size = sizeof(a)/sizeof(int);
	cout << "size = "<<size << endl;
	P1* p = new P1(a, size);
	//p->swap_bubbleSort();
	//p->choicSort();
	p->orderSort();
	cout<<atoi("121");
	cout << "hello world!" << endl;
	system("pause");
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zanglengyu

敲碗要饭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值