常见排序算法实现(c++)

1 排序基本概念

假设含有n个记录的序列为 r 1 , r 2 , . . . , r n r_1,r_2,...,r_n r1,r2,...,rn,其相应的关键字分别为 k 1 , k 2 , . . . , k n k_1,k_2,...,k_n k1,k2,...,kn,需要确定 1 , 2 , . . . , n 1, 2, ..., n 1,2,...,n的一种序列 p 1 , p 2 , . . . , p n p1,p2,...,pn p1,p2,...,pn,使得其对应的关键字满足 k p 1 , k p 2 , . . . k p n k_{p1},k_{p2},...k{pn} kp1,kp2,...kpn(非递减或非递增)关系,即使得序列成为一个按关键字有序得序列 r p 1 , r p 2 , . . . , r p n r_{p1},r_{p2},...,r_{pn} rp1,rp2,...,rpn,这样得操作称为排序

1.1 排序的稳定性

r i = r j r_i = r_j ri=rj,在排序前 r i r_i ri领先于 r j r_j rj,如果排序后 r i r_i ri仍然领先于 r j r_j rj,则称为所用的排序算法是稳定的;反之,若可能使得排序后 r j r_j rj领先于 r i r_i ri,则称为该排序算法是不稳定的。

1.2 内排序和外排序

内排序:排序的整个过程中,待排序的所有记录全部存放在内存中。常见的内排序算法有:冒泡排序、简单选择排序、直接插入排序、希尔排序、归并排序、堆排序、快排等

外排序:排序的记录数太多,不能同时放置在内存中,整个排序过程需要内外存多次交换数据才能进行。

1.3 复杂度分析

算法复杂度
冒泡排序 O ( n 2 ) O(n^2) O(n2)
简单选择排序 O ( n 2 ) O(n^2) O(n2)
直接插入排序 O ( n 2 ) O(n^2) O(n2)
希尔排序 O ( n ∗ l o g n ) O(n*logn) O(nlogn)
堆排序 O ( n ∗ l o g n ) O(n*logn) O(nlogn)
归并排序 O ( n ∗ l o g n ) O(n*logn) O(nlogn)
快排排序 O ( n ∗ l o g n ) O(n*logn) O(nlogn)

2 代码实现

2.1 冒泡排序

2.11 最简单排序(不满足两两比较相邻记录)

#include <iostream>
using namespace std;
int main()
{
	int n;
	int a[100];
	cout << "请输入元素个数:" << endl;
	cin >> n;

	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}

	for (int i = 0; i < n - 1; i++)
	{
		for (int j = i + 1; j < n; j++)
		{
			if (a[i] > a[j])
			{
				int temp;
				temp = a[i];
				a[i] = a[j];
				a[j] = temp;
			}
		}
	}	
	for (int i = 0; i < n; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;

	system("pause");
	system("cls");
	return 0;
}

在这里插入图片描述

2.2 冒泡排序法

冒泡排序是一种比较简单的排序算法。较小的数字如同气泡一样慢慢浮到上面,因此命名为冒泡算法。

注意j从后往前冒泡
比较时,若前者大于后者,则交换次序

#include <iostream>
using namespace std;
int main()
{
	int n;
	int a[100];
	cout << "请输入元素个数:" << endl;
	cin >> n;

	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}

	for (int i = 0; i < n - 1; i++)        
	{
		for (int j = n-1; j >i; j--)
		{
			if (a[j-1] > a[j])                
			{
				int temp;
				temp = a[j-1];
				a[j-1] = a[j];
				a[j] = temp;
			}
		}
	}	
	for (int i = 0; i < n; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;

	system("pause");
	system("cls");
	return 0;
}

2.3 冒泡排序法优化

若数组

a[4] = {2,1,3,4};

则第一次比较后得到:

a[4] = {1,2,3,4};

第一次排序后即完成,后续遍历无作用,切浪费运行效率;
引入flag

#include <iostream>
using namespace std;
int main()
{
	int n;
	int a[100];
	bool flag = true;
	cout << "请输入元素个数:" << endl;
	cin >> n;

	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}

	for (int i = 0; i < n - 1 && flag; i++)
	{
		flag = false;
		for (int j = n-1; j >i ; j--)
		{
			if (a[j-1] > a[j])
			{
				int temp;
				temp = a[j-1];
				a[j-1] = a[j];
				a[j] = temp;

				flag = true;
			}
		}
	}	
	for (int i = 0; i < n; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;

	system("pause");
	system("cls");
	return 0;
}

2.2 简单选择排序

代码实现1:

#include <iostream>
using namespace std;

void selectsort(int a[],int N)
{
	int i=0,j=0,min=0;
	for (i=0;i<N;i++)
	{
		min= i;
		for (j = i+1;j<N;j++)
		{
			if (a[min] > a[j])
			{
				min = j;
			}
		}
		if (min!=i)
		{
			int temp = a[i];
			a[i] = a[min];
			a[min] = temp;
		}
	}
}

int main()
{
	int a[]={9,1,5,3,2,7};
	int N = sizeof(a)/sizeof(a[0]);
	
	selectsort(a,N);
	for (int l = 0;l < N; l++)
		cout << a[l];
		cout <<endl;

	system("pause");
	return 0;
}

代码实现2:

#include <iostream>
using namespace std;

void sort(int* a,int N)
{
	int i, j, min;
	for (i = 0; i < N; i++)
	{
		min = i;
		for (j = i + 1; j < N; j++)
		{
			if (a[j] < a[min])
			{
				min = j;
			}
		}
		if (min != i)
		{
			int temp = a[min];
			a[min] = a[i];
			a[i] = temp;
		}
	}
}

int main()
{
	int aaa[100] = { 0 };
	int N;
	cout << "N:" << endl;
	cin >> N;
	cout << "aaa[" << N << "]:" << endl;
	for (int k = 0; k < N; k++)
	{
		cin >> aaa[k];
	}
	sort(aaa, N);
	
	for (int k = 0; k < N; k++)
	{
		cout << aaa[k];
	}
	cout << endl;
	system("pause");

	return 0;
}

2.3 直接插入排序

直接插入排序的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表

#include <iostream>
using namespace std;

void sort(int a[],int N)
{
	int i=0; 
	int j=0;
	for (i = 1; i < N; i++)
	{
		if (a[i] < a[i - 1])
		{
			int temp = a[i];           //设置哨兵
			for (j = i - 1; a[j] > temp; j--) //若往前插入过程中,遇到a[j]<=temp;则此位置为应该所在的位置
			{
				a[j+1] = a[j];  //记录后移
			}
			a[j + 1] = temp;        //再将哨兵赋值给当前位置
		}
	}
}

int main()
{
	int aaa[100] = { 0 };
	int N;
	cout << "N:" << endl;
	cin >> N;
	cout << "aaa[" << N << "]:" << endl;
	for (int k = 0; k < N; k++)
	{
		cin >> aaa[k];
	}
	sort(aaa, N);
	
	for (int k = 0; k < N; k++)
	{
		cout << aaa[k];
	}
	cout << endl;
	system("pause");

	return 0;
}

2.4 希尔排序

2.5 堆排序

2.5.1 heapinsert 插入一个大值在末端

#include <iostream>
using namespace std;

void swap1(int* a, int i, int j)
{
	int temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}

void heapinsert(int* a, int i)
{
	while (a[i] > a[(i - 1) / 2])
	{
		swap1(a, i, (i - 1) / 2);
		i = (i - 1) / 2;
	}
}


int main()
{
	int a[100] = { 0 };
	int N;

	cout << "n:" << endl;
	cin >> N;

	for (int i = 0; i < N; i++)
		cin >> a[i];

	for (int j = 0; j < N; j++)
		heapinsert(a, j);


	for (int k = 0; k < N; k++)
		cout << a[k];
	cout << endl;

	system("pause");
	return 0;
}

2.5.2 heapfly 其中一个节点值变小

左右两个孩子最大的与它交换
heapsize越界标志:
0-8为数组,但是堆只有0-5,故heapsize=5;

#include <iostream>
using namespace std;
void swap1(int* a, int i, int j)
{
	int temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}
void heapinsert(int* a, int i)
{
	while (a[i] > a[(i - 1) / 2])
	{
		swap1(a, i, (i - 1) / 2);
		i = (i - 1) / 2;
	}
}
void heapfly(int* a, int index, int heapsize)
{
	int left = index * 2 + 1;
	while (left < heapsize)
	{
		int maxindex = left + 1 < heapsize && a[left + 1] > a[left] ? left + 1 : left;
		maxindex = a[maxindex] > a[index] ? maxindex : index;
		if (maxindex == index)//就是它本身,他变小没有影响
			break;
		swap1(a, index, maxindex);
		index = maxindex;
		left = index * 2 + 1;
	}
}
int main()
{
	int a[100] = { 0 };
	int N;
	cout << "n:" << endl;
	cin >> N;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	heapfly(a, 1, 6);
	for (int k = 0; k < N; k++)
		cout << a[k];
	cout << endl;
	system("pause");
	return 0;
}

2.5.3 堆排(优先级队列)

大根堆:将堆顶弹出到小根堆:将堆顶与堆底交换,然后减堆(堆底出),然后堆顶heapfly
小根堆

堆排:

#include <iostream>
using namespace std;

void swap1(int* a, int i, int j)
{
	int temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}
void heapinsert(int* a, int i)
{
	while (a[i] > a[(i - 1) / 2])
	{
		swap1(a, i, (i - 1) / 2);
		i = (i - 1) / 2;
	}
}
void heapfly(int* a, int index, int heapsize)
{
	int left = index * 2 + 1;
	while (left < heapsize)
	{
		int maxindex = left+1 < heapsize && a[left + 1] > a[left] ? left + 1 : left;
		maxindex = a[maxindex] > a[index] ? maxindex : index;
		if (maxindex == index)//就是它本身,他变小没有影响
			break;
		swap1(a, index, maxindex);
		index = maxindex;
		left = index * 2 + 1;
	}
}
void heapsort(int* a, int heapsize)
{
	if (a == nullptr || heapsize < 2)
		return;
	for (int q = 0; q < heapsize; q++)
		heapinsert(a, q);   //0~Q完成大根堆
	swap1(a, 0, --heapsize);
	while (heapsize > 0)
	{	
		heapfly(a, 0, heapsize);
		cout << a[heapsize] << endl;
		swap1(a, 0, --heapsize);
	}
}
int main()
{
	int a[100] = { 0 };
	int N;
	cout << "n:" << endl;
	cin >> N;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	heapsort(a, N);
	for (int k = 0; k < N; k++)
		cout << a[k];
	cout << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

2.6 归并排序

数组小和以及逆序对的问题

#include <iostream>
using namespace std;
void mergesort(int a[], int L, int q, int R)
{
	int n = R - L + 1;
	int* b = new int[n];
	int z = 0;
	int left = L;
	int right = q + 1;
	while(left <= q && right <= R)
		b[z++] = (a[left] <= a[right]) ? a[left++]:a[right++];
	while(left <= q)
		b[z++] = a[left++];
	while(right <= R)
		b[z++] = a[right++];
	for (int m = 0; m < n; m++)
		a[L+m] = b[m];
	delete [] b;
}
 void sort(int a[], int L, int R)
{
	if (L == R)
		return;
	int q = L + ((R - L) >> 1);
	sort(a, L, q);
	sort(a, q+1, R);
	mergesort(a, L, q, R);
}
int main()
{
	int a[6] = {5,2,1,4,9,7};
	sort(a, 0, 5);
	for (int i = 0; i < 6; i++)
		cout << a[i];
	cout << endl;
	system("pause");
	return 0;
}

2.7 快速排序

2.7.1 使用num分界数组(不是排序)

给定一个数组arr,和一个数num;以num为界,数组中小于等于num的数放左边,大于num的数放右边。

#include <iostream>
using namespace std;

int main()
{
	int a[] = { 7,6,2,4 };
	int num = 5;
	int left = 0;
	int right = 3;
	int ll = left - 1;
	int rr = right;
	while (ll != right)
	{
		if (a[left] <= num)
			a[++ll] = a[left++];
		else
		{
			int temp = a[left];
			a[left] = a[right];
			a[right] = temp;
			right--;
		}
	}
	for (int i = 0; i < 4; i++)
		cout << a[i];
	cout << endl;
	system("pause");
	return 0;
}

2.7.2 荷兰国旗问题

给定一个数组arr,和一个数num;以num为界,数组中小于num的数放左边,大于num的数放右边。等于num的放中间。
代码参考左肾:

#include <iostream>
using namespace std;

void exchange(int* arr, int f, int s)
{
	int temp = arr[f];
	arr[f] = arr[s];
	arr[s] = temp;
}

void england(int* a, int l, int r, int num)
{
	int left = l - 1;
	int right = r + 1;
	while (l < right)
	{
		if (a[l] < num)
		{
			//int tem = a[++left];
			//a[left] = a[l];
			//a[l] = tem;
			//l++;
			exchange(a, ++left, l++);
		}
		else if (a[l] > num)
		{
			//int temp = a[l];
			//a[l] = a[--right];
			//a[right] = temp;
			exchange(a, l, --right);
		}
		else
			l++;
	}
}

int main()
{
	int a[100] = { 0 };
	int N;
	int num = 5;
	cout << "N:" << endl;
	cin >> N;

	cout << "a[N]:" << endl;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	cout << "输入为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	england(a, 0, N - 1, num);
	cout << "输出为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;
	system("pause");
	return 0;
}

2.7.3 寻找边界代码

vector版:

#include <iostream>
#include <vector>
using namespace std;
void exchange(int* arr, int f, int s)
{
	int temp = arr[f];
	arr[f] = arr[s];
	arr[s] = temp;
}
void england(int* a, int l, int r, int num, vector<int>& b)
{
	int left = l - 1;
	int right = r + 1;
	while (l < right)
	{
		if (a[l] < num)
			exchange(a, ++left, l++);
		else if (a[l] > num)
			exchange(a, l, --right);
		else
			l++;
	}
	b.push_back(left + 1);
	b.push_back(right - 1);
}
int main()
{
	int a[100] = { 0 };
	int N;
	int num = 5;
	vector<int> bound;
	cout << "N:" << endl;
	cin >> N;

	cout << "a[N]:" << endl;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	cout << "输入为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	england(a, 0, N - 1, num, bound);
	cout << "输出为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	cout << "bound为:";
	for (int i = 0; i < bound.size(); i++)
		cout << bound[i];
	cout << endl;
	system("pause");
	return 0;
}

数组版:b必须为全局变量或在局部环境中声明static,否则局部变量返回值为空。

#include <iostream>
using namespace std;
void exchange(int* arr, int f, int s)
{
	int temp = arr[f];
	arr[f] = arr[s];
	arr[s] = temp;
}
int * partition(int* a, int l, int r, int num)
{
	int left = l - 1;
	int right = r + 1;
	static int b[2] = { 0 };
	while (l < right)
	{
		if (a[l] < num)
			exchange(a, ++left, l++);
		else if (a[l] > num)
			exchange(a, l, --right);
		else
			l++;
	}
	b[0]=(left + 1);
	b[1]=(right - 1);
	return b;
}
int main()
{
	int a[100] = { 0 };
	int N;
	int num = 5;
	int *p;
	cout << "N:" << endl;
	cin >> N;

	cout << "a[N]:" << endl;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	cout << "输入为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	p = partition(a, 0, N - 1, num);
	cout << "输出为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	cout << "bound为:";
	for (int i = 0; i < 2; i++)
		cout << *(p+i);
	cout << endl;
	system("pause");
	return 0;
}

改进partition:vector版

#include <iostream>
#include <vector>
using namespace std;
void exchange(int* arr, int f, int s)
{
	int temp = arr[f];
	arr[f] = arr[s];
	arr[s] = temp;
}
void england(int* a, int l, int r, vector<int>& b)
{
	int left = l - 1;
	int right = r;
	while (l < right)
	{
		if (a[l] < a[r])
			exchange(a, ++left, l++);
		else if (a[l] > a[r])
			exchange(a, l, --right);
		else
			l++;
	}
	exchange(a, l, r);
	b.push_back(left + 1);
	b.push_back(right);
}
int main()
{
	int a[100] = { 0 };
	int N;
	int num = 5;
	vector<int> bound;
	cout << "N:" << endl;
	cin >> N;

	cout << "a[N]:" << endl;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	cout << "输入为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	england(a, 0, N - 1,bound);
	cout << "输出为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	cout << "bound为:";
	for (int i = 0; i < bound.size(); i++)
		cout << bound[i];
	cout << endl;
	system("pause");
	return 0;
}

改进partition:数组版

#include <iostream>
using namespace std;

void exchange(int* arr, int f, int s);
int * partition(int* a, int l, int r);

int main()
{
	int a[100] = { 0 };
	int N;
	int num = 5;
	int *p;
	cout << "N:" << endl;
	cin >> N;

	cout << "a[N]:" << endl;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	cout << "输入为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	p = partition(a, 0, N - 1);
	cout << "输出为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	cout << "bound为:";
	for (int i = 0; i < 2; i++)
		cout << *(p+i);
	cout << endl;
	system("pause");
	return 0;
}
void exchange(int* arr, int f, int s)
{
	int temp = arr[f];
	arr[f] = arr[s];
	arr[s] = temp;
}
int * partition(int* a, int l, int r)
{
	int left = l - 1;
	int right = r;
	static int b[2] = { 0 };
	while (l < right)
	{
		if (a[l] < a[r])
			exchange(a, ++left, l++);
		else if (a[l] > a[r])
			exchange(a, l, --right);
		else
			l++;
	}
	exchange(a, l, r);
	b[0] = (left + 1);
	b[1] = (right);
	return b;
}

2.7.4 经典快速排序

快速排序,左程云是每次选取最右边进行排序。
此题,包括经典排序,均为选取最左边进行排序。参考0731科大讯飞提前批 某种序列题目

选取最右边进行排序
#include <iostream>
#include <vector>
using namespace std;
void exchange(int* arr, int f, int s)
{
	int temp = arr[f];
	arr[f] = arr[s];
	arr[s] = temp;
}
void partiton(int* a, int l, int r, vector<int>& b)
{
	int left = l - 1;
	int right = r;
	while (l < right)
	{
		if (a[l] < a[r])
			exchange(a, ++left, l++);
		else if (a[l] > a[r])
			exchange(a, l, --right);
		else
			l++;
	}
	exchange(a, l, r);
	b.push_back(left + 1);
	b.push_back(right);
}
void quick(int* a, int L, int R)
{
	vector<int> hhh;
	if (L < R)
	{
		partiton(a, L, R, hhh);
		quick(a, L, hhh[0] - 1);
		quick(a, hhh[1] + 1, R);
	}
}

int main()
{
	int a[100] = { 0 };
	int N;
	int num = 5;
	vector<int> bound;
	cout << "N:" << endl;
	cin >> N;

	cout << "a[N]:" << endl;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	cout << "输入为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	quick(a, 0, N - 1);
	cout << "输出为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	cout << endl;
	system("pause");
	return 0;
}

在这里插入图片描述
在这里插入图片描述

选取最左边进行排序
#include <iostream>
#include <vector>
using namespace std;

void exchange(int* arr, int f, int s)
{
	int temp = arr[f];
	arr[f] = arr[s];
	arr[s] = temp;
}

void quickSort(int* A, int start, int end, int N) 
{
	if (start >= end) 
	{
		return;
	}

	int left = start;
	int right = end;
	int val = A[left];

	while (left < right) 
	{
		while (left < right && A[right] >= val) 
		{
			--right;
		}
		while (left < right && A[left] <= val) 
		{
			++left;
		}
		exchange(A, left, right);
	}
	exchange(A, start, left);
	
	cout << "输出为:";
	for (int i = 0; i < N; i++)
		cout << A[i] << " ";
	cout << endl;

	quickSort(A, start, left - 1, N);
	quickSort(A, left + 1, end, N);
}

int main()
{
	int a[1000] = { 0 };
	int N;
	cout << "N:" << endl;
	cin >> N;

	cout << "a[N]:" << endl;
	for (int i = 0; i < N; i++)
		cin >> a[i];

	cout << "输入为:";
	for (int i = 0; i < N; i++)
		cout << a[i] << " ";
	cout << endl;
	cout << "--------------------------" << endl;

	quickSort(a, 0, N - 1,N);

	cout << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

2.7.5 随机快排

主要在于通过随机一个界限值来平均排序的偏向

exchange(a, l + rand()%((r - l) + 1),r);

其中,其他的随机数的范围通式
产生一定范围随机数的通用表示公式是:

  • 要取得[0,n) 就是rand()%n 表示 从0到n-1的数

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;

  • 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;

  • 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;

  • 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。

  • 要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。

  • 要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。

参考:https://www.cnblogs.com/xiaokang01/p/9786751.html

最终代码:

#include <iostream>
#include <vector>
using namespace std;
void exchange(int* arr, int f, int s)
{
	int temp = arr[f];
	arr[f] = arr[s];
	arr[s] = temp;
}
void partiton(int* a, int l, int r, vector<int>& b)
{
	exchange(a, l + rand()%((r - l) + 1),r);
	int left = l - 1;
	int right = r;
	while (l < right)
	{
		if (a[l] < a[r])
			exchange(a, ++left, l++);
		else if (a[l] > a[r])
			exchange(a, l, --right);
		else
			l++;
	}
	exchange(a, l, r);
	b.push_back(left + 1);
	b.push_back(right);
}
void quick(int* a, int L, int R)
{
	vector<int> hhh;
	if (L < R)
	{
		partiton(a, L, R, hhh);
		quick(a, L, hhh[0] - 1);
		quick(a, hhh[1] + 1, R);
	}
}

int main()
{
	int a[100] = { 0 };
	int N;
	int num = 5;
	vector<int> bound;
	cout << "N:" << endl;
	cin >> N;

	cout << "a[N]:" << endl;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	cout << "输入为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	quick(a, 0, N - 1);
	cout << "输出为:";
	for (int i = 0; i < N; i++)
		cout << a[i];
	cout << endl;

	cout << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

2.8 桶排序

若每个数字只出现一次,时间复杂度 O ( N ) O(N) O(N),空间复杂度 O ( N ) O(N) O(N)

#include <iostream>
using namespace std;

int main()
{
	int a[10] = { 5,4,1,8,2,3,6,7,9,0 };
	int n = 10;
	int b[10] = { 0 };
	for (int i = 0; i < 10; i++)
	{
		b[a[i]]++;
	}
	for (int i = 0; i < 10; i++)
	{
		if (b[i])
			cout << i;
	}
	cout << endl;

	system("pause");
	return 0;
}
//if (b[i])
//	cout << i;
//非一次排序
while (b[i])
{

	cout << i;
	b[i]--;
}

补充问题:

给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度 O ( N ) O(N) O(N),且要求不用非基于比较的排序。
java代码:

public class Code_11_MaxGap 
{
	public static int maxGap(int[] nums) 
	{
		//边界检测
		if (nums == null || nums.length < 2) 
		{
			return 0;
		}
		//求数组最大值最小值
		int len = nums.length;
		int min = Integer.MAX_VALUE;
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < len; i++) 
		{
			min = Math.min(min, nums[i]);
			max = Math.max(max, nums[i]);
		}
		//所有数一样大
		if (min == max) {
			return 0;
		}
		//分三个数组,分别存放每个桶是否有值、最小最大值
		boolean[] hasNum = new boolean[len + 1];
		int[] maxs = new int[len + 1];
		int[] mins = new int[len + 1];
		//所属桶号
		int bid = 0;
		for (int i = 0; i < len; i++) 
		{
			bid = bucket(nums[i], len, min, max);
			mins[bid] = hasNum[bid] ? Math.min(mins[bid], nums[i]) : nums[i];
			maxs[bid] = hasNum[bid] ? Math.max(maxs[bid], nums[i]) : nums[i];
			hasNum[bid] = true;
		}
		//遍历求结果
		int res = 0;
		int lastMax = maxs[0];
		int i = 1;
		for (; i <= len; i++) 
		{
			if (hasNum[i]) 
			{
				res = Math.max(res, mins[i] - lastMax);
				lastMax = maxs[i];
			}
		}
		return res;
	}
	//求桶号
	public static int bucket(long num, long len, long min, long max) 
	{
		return (int) ((num - min) * len / (max - min));
	}
}

总结

1 冒泡、选择、插入

#include <iostream>
#include <vector>
using namespace std;
void print(vector<int> a)
{
	int len = a.size();
	for (int i = 0; i < len; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
}
void swap(vector<int> &a, int i, int j)
{
	int temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}
void BubbleSort(vector<int> &a)
{
	int len = a.size();
	bool flag = true;
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 1; j < len - i; j++)
		{
			if (a[j] < a[j - 1])
			{
				swap(a, j, j - 1);
				flag = false;
			}
		}
		if (flag) break;
	}
}
void SelectSort(vector<int> &a)
{
	int len = a.size();
	for (int i = 0; i < len - 1; i++)
	{
		int min = i;
		for (int j = i + 1; j < len; j++)
		{
			if (a[min] > a[j])
			{
				min = j;
			}
		}
		if (min != i)
			swap(a, min, i);
	}
}
void InsertSort(vector<int> &a)
{
	int len = a.size();
	for (int i = 1; i < len; i++)
	{
		for (int j = i - 1; j >= 0 && a[j] > a[j + 1]; j--)
		{
			swap(a, j, j + 1);
		}
	}
}
int main(int argc, char* argv[])
{
	vector<int> a;
	int N;
	cin >> N;
	for (int i = 0; i < N; i++)
	{
		int cur;
		cin >> cur;
		a.push_back(cur);
	}

	//BubbleSort(a);
	//print(a);

	//SelectSort(a);
	//print(a);

	InsertSort(a);
	print(a);
	system("pause");
	return 0;
}

2 归并

数组小和
逆序对

3 快排序

参考2.7.4 选择最左边还是最右边进行快速排序。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值