wpl: 加重パス長。加重パス長を指します。
一連の重みに対応するハフマン ツリーの重み付きパスの長さを見つけるための最も直接的な方法は、最初にハフマン ツリーを構築し、次にすべてのリーフ ノードの重み付きパスの合計を計算することです。
この解決策では、最初にハフマン ツリーを構築し、次に各リーフ ノードに対応する深さをマークし、次にすべてのリーフ ノードを走査する必要があります。
しかし実際には、wpl を解くだけであれば、ハフマン ツリーを構築する必要はなく、深さを解決してリーフ ノードを走査する必要はありません。元のノードと新しく生成されたノードの最小重みを繰り返し加算するだけで済みます。
最初にコードを指定します: (デフォルトの重み配列は順序付けされています)
//默认权重数组w已经有序(从小到大)
//指针p指向当前最小权值的index,初始值给1
//n为数组w的规模
//权重数组w默认1为起始位
int ans=0;
int fastwpl(int w[],int p,int n)
{
if(n<=1) return 0; //没有或只有一个节点,wpl为0;
if (p>= n) return ans; //当p指向最末位(根节点),求解结束
else {
int new_w = w[p] + w[p+1]; //取出两个最小权值,生成新权值
ans += new_w;
//插入新权值节点//
//查找插入位置
int i = p+2; //由于两个最小权值已取出,所以从p+2开始检索
while (new_w > w[i] && i<=n ) i++;
//在i之前插入新权值
for (int j = p + 1; j < i-1; j++) w[j] = w[j + 1];
w[i - 1] = new_w;
//指针后移一位(每次运算,删除两个最小节点,生成一个新节点,故p+1)
p++;
fastwpl(w, p, n);
}
}
アルゴリズムの説明 (次の図のハフマン ツリーは例です):
最も簡単な解決策は次のとおりです。
この記事の解決策は次のとおりです。
つまり、ルート以外のすべてのノードの重みを合計します。
この解決策は不合理に思えます。ノードの経路長がまったく考慮されていないように見えます。実際、「パス長」、つまりリーフの深さの計算は、中間ノードの繰り返しの合計プロセスに暗黙的に含まれます。
たとえば、ノード 2 と 4 の経路長は 3、つまり重み付けされた経路長は 2*3+4*3 であり、2 と 4 を 3 回繰り返し加算することに相当します。
別の考え方では、2 + 4 で構成される新しいノード 6 を追加すると、そのペアに対して +2+4 演算を実行するのと同じになります。
つまり、+2+4+6=+2+4+(2+4)=+2*2+4*2 となります。
同様に、次の演算層では、6 + 5 によって得られる新しいノード 11 を追加することは、6 = 2 + 4 を再度追加することと同じです。
したがって、新しいノードを継続的に追加するプロセスでは、リーフ ノード 2 と 4 のパス長を継続的に反復することと同じになります。
一般に、次のように結論付けることができます。
wpl=ハフマンツリーのすべての非ルートノードの重みの合計を生成します
したがって、一連の重みの最小重み付きパス長を計算するには、リーフ ノードとその新しく生成された重みノードを繰り返し追加するだけで済みます。重み配列が順序付けされている場合、複雑さは O(n) です。
ソートに関しては、クイックソートまたはマージソートを使用できます。