深度优先策略:
1.递归调用的思想。
2.回溯
3.递归调用要设置终止条件。
4.遍历所有可能性。
例题:1-10的全排列
int p[10]={0}; #数组用来放置每个位置存储的数字
bool vis[10]={0}; #bool代数来判断每个数字是否出现过
int n; #代表排列数字的范围
void dfs(int x){
if(x==n+1){
for(int i=0,i<=n,i++)
cout<<p[i]<<"";
cout<<endl;
return;
}
for(int i=0,i<=n,i++)
if(vis[i]=false) {
p[x]=i;
vis[i]=true;
dfs(x+1);
vis[i]=false;
}
}
int main(){
while(cin>>n){
dfs(1);
}
return 0;
}
例题2:程序员爬楼梯。对于一个有n级的梯子,每次可以爬1或3级,共有多少种可能性爬到梯顶。
typedef long long ll;
ll ans,n;
void dfs(ll k){
if(k==n){
ans++;
return;}
else if(k>n){
return;}
dfs(k+1);
dfs(k+3);
}
int main(){
while(cin>>n){
dfs(0);
ans=0;
cout<<ans<<endl;
}
return 0;
}
哈夫曼树
节点的权值路径:节点所处的深度(即节点在第几层上)*节点所附带的权重。
树的带权路径长度:是将树上所有的节点,分别算出它们的权值路径并求和。
哈夫曼树:把权重最大的节点放在根附近,使得整体的带权路径值最小。
节点代码:
typedef struct HTNode{
int weight;
int parent;
int left,right;
}*HuffmanTree;
哈夫曼查找算法:
#原理:首先要找到两个最小的结点。从所有的叶子结点中找出最小的,它们的parent存储为0。
void select(Huffman HF,int n,int* s1,int* s2) //n用来确定HF数组的大小
{
int min; //min用来存储最小的节点在HF数组中位置
for(int i=1,i<=n,i++){
if(HF[i].parent == 0){
min=i;
break;}
for(i=min+1,i<=n,i++){
if(HF[i].parent == 0 && HF[i].weight<HF[min].weight)
min=i;
}
s1=min; //找到第一个最小值的位置,存储给s1
for(int i=1,i<=n,i++){
if(HF[i].parent == 0 && i!=s1){
min=i;
break;}
for(i=min+1,i<=n,i++){
if(HF[i].parent == 0 && HF[i].weight<HF[min].weight && i!=s1)
min=i;
}
s2=min;
}
//查找最小值的思想在于,先找到第一个符合要求的结点,再在其后不停比较其他符合条件的结点,最后存储权值最小的结点位置。
构建哈夫曼树
void createHuffmantree( HuffmanTree& HF,double* weight,int n){
int m=2*n-1; //哈夫曼树的实际结点数是所有叶结点的2倍-1;
HF=(Huffmantree)malloc((m+1)*sizeof(HFNode)) //HF数组的0号位置不使用
for(int i=1,i<=n,i++){
HF[i].wieght=w[i-1];
}
for(int i=n+1,i<m,i++){ //构建哈夫曼树,给父节点赋值
int s1,s2;
select(HF,i-1,s1,s2)
HF[i].weight=HF[s1].weight+HF[s2].weight;
HF[s1].parent=Hf[s2].parent=i;
HF[i].left=s1;
HF[i].right=s2;
}
}