- 排序方法整理(1)
- 1、选择排序
- 2、冒泡排序
- 3、插入排序
- 4、归并排序
- 5、快速排序
- 总结
因为习惯使用vector容器,后续数组均是用vector容器。
选择排序是通过一轮又一轮的比较寻找每一轮的最小值,与最后一个位置进行交换,因此每一轮进行一次交换。
时间复杂度为: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种排序算法中,按照时间复杂度而言最好的应该为归并和快排,但是由于存在递归,所以空间复杂度较高。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)