Куча — волшебная расстановка приоритетов
Создайте минимальную кучу, по очереди удалите верхние значения элементов и реализуйте сортировку кучи от меньшего к большему.
Временная сложность сортировки кучи равна 0 (NlogN).
Куча — это полное бинарное дерево, в котором родительский узел больше или равен (меньше или равен) левому и правому дочерним узлам.
//堆排序-从小到大排序建立最小堆
#include<iostream>
#include<algorithm>
using namespace std;
int h[101];//存放堆的数组
int n;//存放堆的大小
//向下调整函数
void siftdown(int i) //传入需要向下调整的结点编号i
{
int t, flag=0;//flag标记是否需要向下调整
//当i结点至少有右结点且需要向下调整
while( i*2<=n && flag==0 )
{
//判断i结点与左结点的关系,并用t记录较小的结点编号
if( h[i] > h[i*2])
t = i*2;
else
t = i;
//如果i有右结点
if( i*2+1 <= n )
{
if(h[t] > h[i*2+1])//如果右结点值更小,更新最小的结点编号
t = i*2+1;
}
//如果最小结点编号!=i
if( t != i)
{
swap(h[t],h[i]);
i = t;
}
else
flag = 1;
}
}
//建立堆
void creat()
{
int i;
//从最后一个非叶结点依次向上进行调整
for( i=n/2; i>=1; i-- )
{
siftdown(i);
}
}
//删除最小的元素
int deletemin()
{
int t;
t = h[1];//记录堆顶的元素值
h[1] = h[n];//将堆最后一个值赋值给堆顶元素
n--;//堆大小减一
siftdown(1);//从堆顶向下调整建立最小堆
return t;//返回之前记录的堆顶值
}
int main()
{
int num;
scanf("%d", &num);
for(int i=1; i<=num; i++)
{
scanf("%d", &h[i]);
}
n = num;
creat();//建堆
for(int i=1; i<=num; i++)//从小到大输出堆顶值
printf("%d ", deletemin());
return 0;
}
Есть лучший метод для сортировки кучи: построить максимальную кучу и поменять местами h[1] и h[n] по очереди, в это время h[n] является самым большим элементом в массиве. После обмена h[1] необходимо уменьшить, чтобы сохранить характеристики кучи. Уменьшите размер кучи на единицу, то есть на n–, затем поменяйте местами h[1] и h[n] и уменьшите h[1]. Пока размер кучи не равен 1, в настоящее время массив h является отсортированным числом.
//堆排序-从小到大排序建立最大堆
#include<iostream>
#include<algorithm>
using namespace std;
int h[101], n;
void siftdown(int i)
{
int t, flag=0;
while(i*2<=n && flag==0)
{
if( h[i] < h[i*2] )
t = i*2;
else
t = i;
if( i*2+1 <= n )
{
if(h[t] < h[i*2+1])
t = i*2+1;
}
if(t != i)
{
swap(h[t], h[i]);
i = t;
}
else
flag = 1;
}
}
void creat()
{
for(int i=n/2; i>=1; i--)
{
siftdown(i);
}
}
//堆排序
void heapsort()
{
while( n>1 )
{
swap(h[1], h[n]);
n--;
siftdown(1);
}
}
int main()
{
int num;
scanf("%d", &num);
for(int i=1; i<=num; i++)
scanf("%d", &h[i]);
n = num;
creat();
heapsort();
for(int i=1; i<=num; i++)
printf("%d ", h[i]);
return 0;
}
Используйте сортировку кучей, чтобы найти k-е наибольшее или k-е наименьшее число в последовательности.
//求数列中第K小的数
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
int finfKthSmallest(vector<int>& nums, int k)
{
priority_queue<int, vector<int> > Q;//建立最大堆
//注意“vector<int>”与后边的“>”中间有一个空格,否侧程序出错。
for(int i=0; i<nums.size(); i++)
{
if(Q.size()<k)
{
Q.push(nums[i]);
}
else if(Q.top()>nums[i])
{
Q.pop();
Q.push(nums[i]);
}
}
return Q.top();
}
int main()
{
int n, num;
vector<int> nums;
cin >> n;
for(int i=0; i<n; i++)
{
scanf("%d", &num);
nums.push_back(num);
}
printf("%d", finfKthSmallest(nums, 3));
return 0;
}
Приведенная выше ссылка на код: https://blog.csdn.net/weixin_44208324/article/details/104483788
Сначала поймай вора, поймай короля и проверь
//并查集
#include<iostream>
int f[1000]={
0}, n, m, k, sum=0;
//f数组初始化
void init()
{
for(int i=1; i<=n; i++)
f[i]=i;
return ;
}
//找祖宗
int getf(int v)
{
if(f[v]==v)
{
return v;
}
else
{
f[v] = getf(f[v]);
return f[v];
}
}
//靠左原则
void merge(int u, int v)
{
int t1 = getf(f[v]);
int t2 = getf(f[u]);
if(t1 != t2)
{
f[t2] = t1;
}
return ;
}
int main()
{
scanf("%d %d", &n, &m);
init();
int x, y;
for(int i=1; i<=m; i++)
{
scanf("%d %d", &x, &y);
merge(x, y);
}
for(int i=1; i<=n; i++)
{
if(f[i] == i)
sum++;//独立树的个数
}
printf("%d", sum);
return 0;
}
другие алгоритмы
Дерево отрезков, массив деревьев, дерево Trie (словарное дерево), бинарное дерево поиска, красно-черное дерево (сбалансированное бинарное дерево поиска) и т. д.