堆排序代码如下:
#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。