3.详解桶排序以及排序内容大总结---C++版左程云耗时100天打造算法与数据一周刷爆LeetCode

堆排序代码如下:

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

void heapInsert(vector<int>& arr, int i);
void heapify(vector<int>& arr, int i, int heapSize);
void swap(int& a, int& b);

void print(vector<int> arr);
void  heapSort(vector<int> &arr) {
	if (arr.empty() || arr.size() < 2)
		return;
	for (int i = 0; i < arr.size(); i++)
	{
		heapInsert(arr, i);
		//print(arr);
		//cout << endl;
	}//插入数组
	//print(arr);
	int heapSize = arr.size()-1;
	while (heapSize > 0) {
		swap(arr[0], arr[heapSize]);
		heapSize--;
		heapify(arr, 0, heapSize);
		
	}
}
void heapInsert(vector<int> &arr, int i)
{
	int father = (i - 1) / 2;
	while (arr[i] > arr[father])
	{
		
		swap(arr[i], arr[father]);
		i = (i - 1) / 2;
		father = (father - 1) / 2;
	}
}

void heapify(vector<int>& arr, int i,int heapSize) {
	int leftLeave = 2 * i + 1;
	int rightLeave = 2 * i + 2;
	while (leftLeave <= heapSize)
	{
		int largest = rightLeave <= heapSize && arr[rightLeave] > arr[leftLeave] ? rightLeave : leftLeave;
		largest = arr[largest] > arr[i] ? largest : i;
		if (largest == i)
			break;
		swap(arr[largest], arr[i]);
		i = largest;
		leftLeave = 2 * i + 1;
		rightLeave = 2 * i + 2;
	}

}

void swap(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}

void print(vector<int> arr) {

	for (int i = 0; i < arr.size(); i++)
		cout << arr[i] << " ";
}

其中可以对heapInsert函数进行改写,可以理解为将叶子作为一颗小树,逐渐在小树的顶部添加数字进行heapify操作,因此可以改下为如下部分:

void  heapSort(vector<int> &arr) {
	if (arr.empty() || arr.size() < 2)
		return;
	//for (int i = 0; i < arr.size(); i++)
	//{
	//	heapInsert(arr, i);
	//	//print(arr);
	//	//cout << endl;
	//}//插入数组
	for (int i = arr.size() - 1; i >= 0; i--)
		heapify(arr, i, arr.size()-1);
	//print(arr);
	int heapSize = arr.size()-1;
	while (heapSize > 0) {
		swap(arr[0], arr[heapSize]);
		heapSize--;
		heapify(arr, 0, heapSize);
		
	}
}

堆排序改编:

对一个数组,元素排序前后元素移动的位置不会超过k,采用哪种方式排序最快?

#include<iostream>
#include<vector>
#include<queue>
#include <algorithm>
using namespace std;
//对一个数组排序,元素排序前后位置移动不会超过k
void PriorityQueue(vector<int> &arr,int k) {


	int length = arr.size();
	priority_queue<int,vector<int>,greater<int>> pq;//greater 小根堆 less 大根堆
	int index = 0;
	for (; index < min(length, k); index++)
		pq.push(arr[index]);
	int i = 0;
	for (; index < length; i++)
	{
		arr[i] = pq.top();
		pq.pop();

		pq.push(arr[index]);
		index++;
	}
	while (!pq.empty())
	{
		
		arr[i++] = pq.top();
		pq.pop();
	}
}

测试案例:

#include<iostream>
#include<vector>
using namespace std;
#include"priorityQueue.h"
#include"heapSort.h"
int main() {
	vector<int> arr = {3, 2, 1, 6, 5, 4, 9, 8, 7};
	print(arr);
	cout << endl;
	//vector<int >arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	 PriorityQueue(arr,  3);
	 print(arr);
	return 0;
}

运行结果:

我们这里设置了k=3,因此在输入数组时,需要对数组进行相应的规定,由代码可知arr满足条件。

除此之外,本课程还用到了函数运算符重载,我们这里也做一遍复习

#include<iostream>
#include<vector>
using namespace std;
//#include"operator.h"
class Person
{

public:
	Person(string name, int age)
	{
		this->m_name = name;
		this->m_age = age;
	};
	bool operator> (Person& p2)
	{
		if (this->m_age > p2.m_age)
			return true;
		else
			return false;
	}
	string m_name;
	int  m_age;
};
int main() {
	Person p1("wangdong", 15);
	Person p2("hdl", 23);
	if (p1 > p2)
		cout << "老大是第一位" << endl;
	else
		cout << "老大是第二位" << endl; 

	return 0;
}

基数排序

#include<iostream>
#include<vector>
#include<queue>
#include <algorithm>
using namespace std;
int getTimes(vector<int>& arr);
void print1(vector<int> arr);
void radixSort(vector<int>& arr)
{
	if (arr.empty() == true || arr.size() < 2)
		return;
	int times=getTimes(arr);
	//cout << times << endl;

	vector<int>bucket(arr.size());
	for (int i = 0; i < times; i++)
	{
		vector<int>count(10);

		cout << "第" << i << "次循环" << endl;
		for (int j = 0; j < arr.size(); j++) //获得每个数字的个数
		{
			int m = (arr[j] / (int)pow(10, i)) % 10;
			count[m]++;
			cout << m << " ";
			
		}
		cout << endl;
		//cout << count[1] << endl;
		for (int j = 1; j <10; j++)  //每个位置上是小于当前数字的个数
		{
			count[j] += count[j - 1];
		}
		//cout << count[9] << endl;
		for (int j = arr.size() - 1; j >= 0; j--)
		{
			int m = (arr[j] / (int)pow(10, i)) % 10;
			bucket[count[m] - 1] = arr[j];
			count[m]--;
		}
		print1(bucket);
		cout << endl;
		for (int j = 0; j < arr.size(); j++)
			arr[j] = bucket[j];
		print1(arr);
		cout << endl;
		cout << "第" << i << "次循环结束" << endl;
	}

}

int getTimes(vector<int>& arr) {
	int max = arr[0];
	int j = 0;
		for (int i = 1; i < arr.size(); i++)
			max = max > arr[i] ? max : arr[i];
		for (; max > 0; j++)
		{
			//cout << max << endl;
			max = max / 10;
		}
		return j;
}

void print1(vector<int> arr) {

	for (int i = 0; i < arr.size(); i++)
		cout << arr[i] << " ";
}

排序算法稳定性:若在排序数组中,值相同的数在排序后与排序前相对位置不发生改变,则称这个排序算法稳定。

以选择排序为例,比如说数组为3,3, 3,1,我们可以发现当遍历到1时,会和第一个3进行交换,这样就会打乱3的相对位置。以冒泡排序为例,交换的是相邻的两个数,当两个相邻的数相等时,不发生交换,因此是稳定的。插入排序也是稳定的,以上三个排序时间复杂度为N方。

归并排序由于会对排序区间进行划分,也是稳定的;快速排序不具有稳定性,堆排序也不具有稳定性(根据二叉树),基数排序由于出入同操作,具有次序,因此具有稳定性,以上排序时间复杂度T=NlogN。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值