ヒープ - 魔法の優先順位付け
最小限のヒープを作成し、上位の要素値を順番に削除し、小さいものから大きいものへのヒープのソートを実装します。
ヒープソートの時間計算量は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] を下方に調整する必要があります。ヒープのサイズを 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;
}
他のアルゴリズム
線分木、木配列、トライ木(辞書木)、二分探索木、赤黒木(平衡二分探索木)など。