C++学习——数据结构——排序方法整理(1)

C++学习——数据结构——排序方法整理(1),第1张

排序方法整理(1)

文章目录
  • 排序方法整理(1)
  • 1、选择排序
  • 2、冒泡排序
  • 3、插入排序
  • 4、归并排序
  • 5、快速排序
  • 总结

因为习惯使用vector容器,后续数组均是用vector容器。

1、选择排序

选择排序是通过一轮又一轮的比较寻找每一轮的最小值,与最后一个位置进行交换,因此每一轮进行一次交换。

时间复杂度为:O(N2)

选择排序:

#include
#include
using namespace std;

//输出容器中的数
void print(vector<int> v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << (*it) << endl;
	}
}

//选择排序算法
void choicesort(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		vector<int>::iterator min = it;
		for (vector<int>::iterator it1 = it + 1; it1 != v.end(); it1++)
		{
			if (*it1 < *it) min = it1;
		}
		//寻找到一轮中的最小值进行一次交换
		swap(*it, *min);
	}
}

int main()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(8);
	v.push_back(7);
	v.push_back(9);
	v.push_back(6);


	choicesort(v);
    
	print(v);
	system("pause");
	return 0;
}

2、冒泡排序

冒泡排序与选择排序不一样的是:冒泡排序每一次都进行了交换,每一次比较后将最大的给最后一个,这样可以保证每一轮循环最后的一位数便是最大值。

冒泡排序:

void bubblesort(vector<int>& v)
{
//细节:终点位置应该为begin+1,循环比较遍历终点应该为it-1
	for (vector<int>::iterator it = v.end(); it != v.begin()+1; it--)
	{
		for (vector<int>::iterator it1 = v.begin(); it1 != it - 1; it1++)
		{
			if (*it1 > * (it1 + 1)) swap(*it1, *(it1 + 1));
		}
	}
}

时间复杂度为:O(N2)

3、插入排序

插入排序的思想是从左至右依次保证有序,首先保证0号位和1号位数据有序,接下来插入2号位的数,保证0,1,2号位共3个数字有序排列,依次进行至最后一个位置。

时间复杂度为O(N)~O(N2)

插入排序:

void insertsort(vector<int>& v)
{
for (vector<int>::iterator it = v.begin()+1; it != v.end(); it++)
	{
			for (vector<int>::iterator it1 = it - 1; (it1 >= v.begin()) && (*it1 > * (it1 + 1)); it1--)
			{
				swap(*it1, *(it1 + 1));
				//防止指针越界
				if (it1 == v.begin())
					break;
			}
	}
}
4、归并排序

归并排序中应用到了递归的思想。

首先找到数组中的中间的位置,然后左边和右边分别排序,然后另起一个数组,左指针后右指针分别遍历左右排好序的数组,实现该数组是左右排好序的数组的综合,即新数组满足有序。

依次递归选择中间值,最终实现排序整个数组。

时间复杂度O(NlogN)

归并排序:

static void merge(vector<int>& v, int L, int R)
{
	if (L == R) return;
	int mid = L + (R - L) / 2;
	//int mid = L + ((R - L) >> 1);
	merge(v, L, mid);
	merge(v, (mid+1), R);
	promerge(v, L, mid, R);
}

static void promerge(vector<int>& v, int L, int mid, int R)
{
	vector<int> h;
	vector<int>::iterator it = v.begin();
	int p1 = L;
	int p2 = mid + 1;
	while (p1 <= mid && p2 <= R)
	{
		if (*(it + p1) <= *(it + p2))
		{
			h.push_back(*(it + p1));
			p1++;
		}
		if (*(it + p1) > *(it + p2))
		{
			h.push_back(*(it + p2));
			p2++;
		}
	}

	while (p1 <= mid)
	{
		h.push_back(*(it + p1));
		p1++;
	}

	while (p2 <= R)
	{
		h.push_back(*(it + p2));
		p2++;
	}

	vector<int>::iterator itp = h.begin();
	for (int i = 0; i < h.size(); i++)
	{
		//此处L容易漏掉
		*(it +L + i) = *(itp + i);
	}
}
5、快速排序

快速排序根据划分方法一共有3个版本,1.0版本是以数组中末端位置的值作为compare,将<=和>的分开递归,2.0是以数组中末端位置的值作为compare,将<,=,>的三个部分分开再递归,3.0是在2.0的基础上随机选择compare的值,再按照2.0的版本递归,前两者的时间复杂度都是O(N2),最后一个由于是随机选择,因此为O(NlogN)。

下列代码是3.0的版本。

3.0快速排序:

//其中,L表示待排列数组的起始点序号,R代表待排列数组终止点序号
void quicksort(vector<int>& v, int L, int R)
{
	if (L < R)
	{
		int left = L;
		int right = R;
		int left_num = 0;
		int right_num = 0;
		vector<int>::iterator its = v.begin();
		int i = (rand() % ((R - L) + 1)) + L;  //生成一个0~size-1的整数
		swap(*(its+ i), *(its + R));
		//vector::iterator its = v.begin();
		int compare = *(its + R);
		int ptr = L;
		while (ptr <= right)
		{
			if (*(its + ptr) < compare)
			{
				swap(*(its + left), *(its + ptr));
				left++;
				ptr++;
				left_num++;
			}

			else if (*(its + ptr) == compare)
			{
				ptr++;
			}

			else if (*(its + ptr) > compare)
			{
				swap(*(its + ptr), *(its + right));
				right--;
				right_num++;
			}
		}
		//此处将compare与>区域第一个交换
		//swap(*(its + right), *(its + R));
		//left, right = quicksort_p(v, L, R);
		quicksort(v, L, L + left_num - 1);
		quicksort(v, R - right_num + 1, R);
	}
	else return;
}

总结

前面的5种排序算法中,按照时间复杂度而言最好的应该为归并和快排,但是由于存在递归,所以空间复杂度较高。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/673610.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-19
下一篇 2022-04-19

发表评论

登录后才能评论

评论列表(0条)

保存