2020 C / C ++選択されたインタビューの質問と回答(3)

ヒープソートのアイデア

ヒープは完全なバイナリツリーです。
完全なバイナリツリーは次のとおりですバイナリツリーの深さがhの場合、h番目のレイヤーを除く各レイヤーのノード数(1〜h-1)が最大数に達し、h番目のレイヤーのすべてのノードすべてが完全なバイナリツリーである左端に継続的に集中しています。
ヒープは2つのプロパティを満たします。ヒープの各親ノードの値がその子ノードよりも大きい(または小さい)ことと、ヒープの左右のサブツリーもそれぞれヒープです。
ヒープは、最小のヒープと最大のヒープに分けられます。最大ヒープは、各親ノードの値が子ノードよりも大きいことを意味し、最小ヒープは、各親ノードの値が子ノードよりも小さいことを意味します。並べ替えの要件が小さいものから大きいものまでの場合、最大のヒープを構築する必要があり、その逆も同様です。
ヒープのストレージは、通常、アレイを使用して実装されます。親ノードの配列添え字がiの場合、左右のノードの添え字は(2 i + 1)と(2 i + 2)です。子ノードの添え字がjの場合、親ノードの添え字は(j-1)/ 2です。
完全なバイナリツリーでは、要素がn個ある場合、ヒープ内の最後の親ノードの位置は(n / 2-1)です。
アルゴリズムのアイデア
ヒープを構築するヒープを
調整するヒープ
の一番上の要素とヒープの最後の要素を
ここに写真の説明を挿入
交換するその他のインタビューの質問交換グループ960994558を研究する

配列a [8] = {100,33,3,7,11,6,8,5}があるとします。最初に、完全なバイナリツリーを構築する必要があります。
以下に示すように:
ここに写真の説明を挿入

次に、各親ノードに従って分割を行います。写真が示すように:

ここに写真の説明を挿入

アルゴリズムは、各親ノードをそれ自体の子ノードと比較してから交換することです。例によると、最大ヒープを確立するには、各親ノードの値が子ノードよりも大きい必要があります。順序は、最後の親ノードから(左から右、下から上)です。したがって、最初の親ノードは7で、配列の添え字は3です。黄色の領域で親ノードと子ノードを比較したところ、親ノードはすでに子ノードよりも大きいため、交換する必要はありません。次のシーケンスは紫色のボックス内のバイナリツリーです。これは、配列の添え字2と番号3を親ノードとする番号3です。左から右に、右の子の値が親ノードよりも大きいことがわかります。右側のノードと親ノードの間で値を交換します。交換されたヒープを図に示します。

ここに写真の説明を挿入

交換が終わったら、青いボックスのバイナリツリーを見てください。これは、配列の添え字が1で33が親ノードである番号33です。その子ノードが親ノードよりも大きいかどうかを確認します。親ノードよりも大きくないことがわかった場合は、交換は必要ありません。現時点では、この完全なバイナリツリーはすでにヒープになっています。
次に、ヒープの一番上の要素をヒープの最後の要素と交換し、最後の要素を完全なバイナリツリーから削除する方法について説明します。

ここに写真の説明を挿入

このとき、完全バイナリツリーでは、100の要素を削除した後、完全バイナリツリーがヒープの性質を満たさないため、調整を行う必要があります。このとき、各調整はルートノード(ヒープの作成とは異なります)と親から調整する必要があります。ノードと子ノードが交換された後、交換の子ノードまでトレースする必要があります(水色でマークされた部分を使用します)。

ここに写真の説明を挿入

この時点で33と5の位置が入れ替わっているので、親ノードとして5から始めて、子ノードと比較する必要があります。このとき、子ノードと親ノードの最大値は11、次に11と親ノード(つまり、 5)ポジションを交換します。

ここに写真の説明を挿入

この時点で、ヒープが調整され、ヒープの一番上の要素がヒープの最後の要素と交換されます。つまり、33と3が交換され、33が完全なバイナリツリーの外側に縮小されます。
ここに写真の説明を挿入

このとき、根元から再度パイルを調整します。

ここに写真の説明を挿入

ここに写真の説明を挿入

この時点でパイルを調整した後、パイルの一番上の要素と最後の要素が交換されます。つまり、11と6が交換され、11は完全なバイナリツリーから外れます。

ここに写真の説明を挿入

このとき、完全なバイナリツリーを調整します。つまり、白で塗りつぶされた要素を調整します。ルートから開始し、上記の方法に従います。

ここに写真の説明を挿入

このとき、それは別の調整されたパイルであり、一番上の要素を最後の要素と交換します。

ここに写真の説明を挿入

次に、完全なバイナリツリーを調整します

ここに写真の説明を挿入

このとき、一番上の要素と最後の要素を交換します
ここに写真の説明を挿入

次に、完全なバイナリツリーを調整します

ここに写真の説明を挿入

最後に、上位の要素を交換します。

ここに写真の説明を挿入

最終調整:

ここに写真の説明を挿入

最後の上位要素の交換:

ここに写真の説明を挿入

この時点で、配列はすでに順序付き配列であり、生の順序付き配列です。forループを使用して出力してください。

Linuxビューファイルサイズコマンド。

  1. statコマンドを使用して表示する
    statコマンドは通常、ファイルのステータス情報を表示するために使用されます。statコマンドの出力情報は、lsコマンドの出力情報よりも詳細です。
  2. wcコマンドの使用
    wcコマンドは通常、テキストの行数やファイルが占めるバイト数などのファイル情報をカウントするために使用されます。
  3. duコマンドを使用するduコマンド
    は通常、ファイルとディレクトリが占めるスペースをカウントするために使用されます。
  4. lsコマンドを使用するlsコマンド
    は通常、ファイルとディレクトリのアクセス許可、所有者、対応するグループ、ファイルサイズ、変更時刻、ファイルパス、その他の情報を含むファイルとディレクトリの情報を表示するために使用されます。

  5. ほとんどのLinuxシステムでllコマンド(実際にはls -lのエイリアス)を使用します。ls-lのエイリアスはllに設定されているため、llコマンドはなく、llは単なるエイリアスコマンドです。
    Linuxはllコマンドを使用してファイルサイズを表示します

ブルームフィルターアルゴリズム

ブルームフィルターは、ハッシュ関数と組み合わせたバイナリベクトルを使用して、セットにデータがすでに存在するかどうかを記録します。
ブルームフィルターの実行プロセスは次のとおりです。
最初にSIZEビットを含むビットセットを適用し、すべてのビットを0に設定します。
次に、いくつかの(k)個の異なるハッシュ関数を使用してターゲットデータをハッシュし、k個のハッシュ値を取得し(ハッシュ値がSIZEのサイズを超えないようにします)、ビットセットのハッシュ値を添え字として使用しますのビット値は1に設定されます。k個のハッシュ関数が使用されるため、データを記録するための情報により、ビットセットのk個のビット値が1に設定されます。
ハッシュ関数の安定性により、ビットセット内の同じデータの任意の2つの部分に対応するkビット位置は完全に同じです。次に、データがビットセットに記録されているかどうかを検出する場合、ビットセットの対応する位置にあるデータのk個のハッシュ値が1としてマークされているかどうかを確認するだけで済みます。ハッシュ値に対応するビット位置が1としてマークされていない場合は、値が記録されていないことを示しています。
使用例
ブルームフィルターの例は次のとおりです。
ここに写真の説明を挿入

一般的なプロセスは次のとおりです。
最初にバイナリ配列を初期化し、長さをL(図では8)に設定し、初期値はすべて0です。
A1 = 1000でデータを書き込む場合、Hハッシュ関数の計算(ここでは2回)を実行する必要があります。HashMapと同様に、計算されたHashCodeとLは変調され、0と2に配置されます。の値は1に設定されます。
A2 = 2000は、4と7の位置を1に設定するのと同じです。
存在するかどうかを判断する必要があるB1 = 1000がある場合、2つのハッシュ操作も実行して0と2に配置します。この時点で、それらの値はすべて1であるため、B1 = 1000がセットに存在すると見なされます。
B2 = 3000の場合、同じことが言えます。最初のハッシュがインデックス= 4にある場合、配列内の値は1であるため、2番目のハッシュ操作が実行され、結果はインデックス= 5にあり、値は0であるため、B2 = 3000はセットに存在しないと見なされます。長所
と短所
長所
時間の複雑さはO(n)であり、ブルームフィルターは要素自体を格納する必要がなく、ビット配列を使用し、小さなスペースを占有します。
短所
ブルームフィルタリングにより、特定のセットに数値が存在しないと正確に判断できますが、セットに存在すると結論付けると、ブルームフィルタリングは誤検知になります(異なるデータのセットが2つあるが、ハッシュ値が複数ある場合があります)。まったく同じ状況)。ただし、ビットセットのサイズ(つまりSIZE)とハッシュ関数の数を制御することで、競合の可能性を非常に狭い範囲で制御したり、追加のホワイトリストを作成してハッシュ競合の問題を完全に解決したりできます。
誤判定率の計算式は(1-e(-nk / SIZE))kです。ここで、nはターゲットデータの数、SIZEはビットセットのサイズ、kは使用されるハッシュ関数の数です。1,000万個あると仮定します。処理するデータのビットセットサイズは2 ^ 30(約10億、128MBのメモリを占有)です。9つの異なるハッシュ関数を使用して、任意の2つのデータの計算されたハッシュ値は9回同じです。 (順序に関係なく)確率は2.6e-10で、38億分の1です。

非負の整数のセットで構成される配列hが与えられると、それはヒストグラムのセットの高さを表します。ここで、各列の幅は1です。このヒストグラムのグループで形成できる最大の長方形の領域を見つけます。入力パラメータhは、各列の高さを表す整数配列であり、領域の値を返します。説明を入力してください:

入力は2行で構成され、最初の行には整数n(
1≤n≤10000 が含まれ2番目の行にはh配列の各値を表すn個の整数が含まれます。h_i(1≤h_i≤1,000,000)
出力の説明:
整数を出力します、最大のマトリックス領域を表します。

入力例1:
6
2 1 5 6 2 3

出力例
1:10

#include <bits / stdc ++。h>
using namespace std;

const int maxn = 10000 + 5;
typedef long long ll;
int h [maxn]、l [maxn]、r [maxn];

int main()
{ // freopen “ in.txt”、“ r”、stdin); int n; scanf( "%d"、&n); for(int i = 1; i <= n; i ++)scanf( "%d"、&h [i]); l [1] = 0; for(int i = 2; i <= n; i ++){ int lp = i-1; while(h [lp]> = h [i])lp = l [lp]; l [i] = lp; } r [n] = n + 1; for(int i = n-1; i> = 1; i –){ int hp = i + 1; while(h [hp]> = h [i])hp = r [hp]; r [i] = hp; } ll ans = 0; for(int i = 1; i <= n; i ++)ans = max(ans、(ll)h [i] *(r [i] -l [i] -1)); printf( "%lld \ n"、ans); 0を返します。}


























テキストから実行可能ファイルへのC ++ソースファイルのプロセス?

C ++ソースファイルの場合、通常、テキストから実行可能ファイルまで4つのプロセスが必要です。
前処理段階:ソースコードファイル内のファイル包含関係(ヘッダーファイル)とプリコンパイル済みステートメント(マクロ定義)の分析と置換により、プリコンパイル済みファイルが生成されます。 。
コンパイル段階:前処理後にコンパイル済みファイルを特定のアセンブリコードに
変換し、アセンブリファイルを生成します。アセンブリ段階:コンパイル段階で生成されたアセンブリファイルをマシンコードに変換し、再配置可能なオブジェクトファイルを生成します。
リンク段階:複数のオブジェクトファイルそして、必要なライブラリは最終的な実行可能オブジェクトファイルにリンクされています
。mallocの原理について、brkシステム呼び出しとmmapシステム呼び出しの機能は何ですか?
malloc関数は、メモリを動的に割り当てるために使用されます。メモリの断片化とシステム呼び出しのオーバーヘッドを削減するために、mallocはメモリプール方式を使用します。最初にメモリの大きなブロックをヒープ領域として適用し、次にブロックをメモリ管理の基本単位として使用して、ヒープを複数のメモリブロックに分割します。ユーザーがメモリを申請すると、適切な空きブロックがヒープ領域から直接割り当てられます。mallocは、暗黙的なリンクリスト構造を使用して、ヒープを割り当てられたブロックと割り当てられていないブロックを含むさまざまなサイズの連続ブロックに分割します。同時に、mallocは、明示的なリンクリスト構造を使用してすべての空きブロックを管理します。つまり、二重リンクリストを使用して空きブロックを接続します。一緒に、各空きブロックは、連続した未割り当てのアドレスを記録します。
メモリが割り当てられると、mallocは暗黙のリンクリストを介してすべての空きブロックをトラバースし、割り当ての要件を満たすブロックを選択します。メモリがマージされると、mallocは境界表記法を使用して、各ブロックの前後のブロックが割り当てられているかどうかを判断します。ブロックマージを実行するかどうか。
mallocがメモリに適用される場合、通常はbrkまたはmmapシステム呼び出しを介して適用されます。要求されたメモリが128K未満の場合、システム関数brkを使用してヒープ領域に割り当てます。要求されたメモリが128Kを超える場合、システム関数mmapを使用してマッピング領域に割り当てます。

共有メモリに関連するAPIは何ですか?

Linuxでは、さまざまなプロセスが同じ論理メモリにアクセスでき、一連のAPIが提供されます。ヘッダーファイルはsys /shm.hにあります。
1)新しい共有メモリを作成します
。shmgetintshmget(key_t key、size_t size、int shmflg);
key:共有メモリのキー値。共有メモリの一意のマークとして理解できます。
size:共有メモリサイズ
shmflag:作成プロセスおよびその他のプロセスの読み取りおよび書き込み権限ID。
戻り値:対応する共有メモリ識別子、失敗時に-1を返し
ます2)共有メモリを現在のプロセスのアドレススペースに接続しますshmat
void * shmat(int shm_id、const void * shm_addr、int shmflg);
shm_id:共有メモリ識別子
shm_addr:共有メモリが現在のプロセスに接続されているアドレス(通常は0)を指定します。これは、システムが選択することを意味します。
shmflg:フラグビット
戻り値:共有メモリの最初のバイトへのポインタ。失敗すると-1を返します
。3)現在のプロセスが共有メモリを分離します
。shmdtintshmdt(const void * shmaddr);
4)共有メモリshmctl
とsemaphoresemctlを制御します機能は似ており、共有メモリを制御します
int shmctl(int shm_id、int command、struct shmid_ds * buf);
shm_id:共有メモリ識別子
コマンド:3つの値があります
IPC_STAT:共有メモリのステータスを取得し、共有メモリのshmid_ds構造をbufにコピーします。
IPC_SET:共有メモリの状態を設定し、bufを共有メモリのshmid_ds構造にコピーします。
IPC_RMID:共有メモリの削除
buf:共有メモリ管理構造。

反応器モデルの構成は何ですか。

リアクターモデルでは、メインスレッドがファイルの説明でイベントが発生したかどうかの監視のみを担当する必要があり、発生した場合は、すぐにワーカースレッドにイベントを通知します。さらに、メインスレッドは他の実質的な作業を行わず、データの読み取りと書き込みを行い、新しい情報を受け入れます。クライアント要求の接続と処理は、ワーカースレッドで完了します。モデルは次のように構成されています。
ここに写真の説明を挿入

1)ハンドル:オペレーティングシステムのハンドルは、オペレーティングシステムレベルでのリソースの抽象化であり、開いているファイル、接続(ソケット)、タイマーなどがあります。Reactorモードは通常、ネットワークプログラミングで使用されるため、通常、ネットワーク接続であるSocketHandleを指します。
2)同期イベントデマルチプレクサ(同期イベントマルチプレクサ):一連のイベントがハンドルに到着するのをブロックして待機します。ブロックして戻りを待機している場合は、返されたハンドルでブロックせずに、返されたイベントタイプを実行できることを意味します。このモジュールは通常、オペレーティングシステムの選択を使用して実装されます。
3)Initiation Dispatcher:EventHandlerのコンテナであるEvent Handlerの管理に使用され、EventHandlerの登録、削除などに使用されます。さらに、Reactorモードの入り口として、同期イベントデマルチプレクサのselectメソッドを呼び出して、イベントが戻るのを待機するのをブロックします。戻るときは、イベントが発生したハンドルに従って対応するイベントハンドラーに配布します。つまり、EventHandlerのhandle_event()メソッドをコールバックします。
4)イベントハンドラー:InitiationDispatcherのコールバックのイベント処理メソッド:handle_event()を定義します。
5)具体的なイベントハンドラー:特定のイベント処理ロジックを実装するイベントEventHandlerインターフェイス。

Linux仮想アドレススペースに聞いてもいいですか

物理メモリで同時に実行されているときに、異なるプロセスが物理メモリで競合したり踏みつけたりするのを防ぐために、仮想メモリが使用されます。
仮想メモリテクノロジは、実行中のプロセスでさまざまなプロセスを作成します。これは、それらだけが現在のシステムの4Gメモリを占有していることを示しています。すべてのプロセスは同じ物理メモリを共有し、各プロセスは現在必要な仮想メモリ空​​間を物理メモリにマッピングして保存するだけです。実際、各プロセスが作成およびロードされると、カーネルはプロセスの仮想メモリレイアウトを「作成」するだけです。具体的には、プロセス制御テーブルのメモリ関連のリンクリストを初期化します。実際、仮想メモリの場所に対応するプログラムデータをすぐに配置するわけではありません。そして、コード(.text.dataセクションなど)が物理メモリにコピーされ、仮想メモリとディスクファイル間のマッピング(メモリマッピングと呼ばれる)を確立するために、対応するプログラムが実行されるまで待機します。ページ障害例外が渡されます。データをコピーします。また、実行中は動的にメモリを割り当てる必要があります。たとえば、mallocの場合、仮想メモリのみが割り当てられるため、この仮想メモリに対応するページテーブルエントリが設定されます。実際にプロセスがこのデータにアクセスすると、不具合が発生します。ページが異常です。
リクエストページングシステム、リクエストセグメンテーションシステム、リクエストセグメントページングシステムはすべて仮想メモリを対象としており、メモリと外部メモリ間の情報置換はリクエストを通じて実現されます。
仮想メモリの利点:
1。アドレススペースを拡張します
。2。メモリ保護:各プロセスは独自の仮想メモリアドレススペースで実行され、相互に干渉することはありません。仮想ストレージは、特定のメモリアドレスへの書き込み保護も提供し、コードまたはデータの悪意のある改ざんを防ぐことができます。
3.公平なメモリ割り当て。仮想ストレージを使用した後、各プロセスは同じサイズの仮想ストレージスペースを持つことに相当します。
4.プロセスが通信するとき、それは仮想メモリ共有によって実現できます。
5.ライブラリファイル内のコードなど、異なるプロセスが同じコードを使用する場合、そのようなコードのコピーを1つだけ物理メモリに保存できます。異なるプロセスは、メモリを節約するために独自の仮想メモリをマップするだけで済みます。
6.仮想メモリはマルチプログラミングシステムでの使用に非常に適しており、多くのプログラムフラグメントが同時にメモリに保存されます。プログラムがその一部がメモリに読み込まれるのを待つとき、CPUを別のプロセスに渡して使用させることができます。複数のプロセスをメモリに保持でき、システムの同時実行性が向上します
。7 プログラムが連続メモリ空間を割り当てる必要がある場合、仮想メモリ空​​間に連続空間を割り当てるだけでよく、実際の物理メモリの連続空間は必要ありません。フラグメンテーションを使用できます。

仮想メモリのコスト:

1.仮想メモリの管理には、追加のメモリを使用する多くのデータ構造の確立が必要
です。2。仮想アドレスを物理アドレスに変換すると、命令の実行時間が長くなります。
3.ページのスワップインとスワップアウトにはディスクI / Oが必要であり、これには非常に時間がかかります
。4 ページ内のデータの一部しかない場合、メモリを浪費します。

オペレーティングシステムでページ障害が中断されますか

malloc()やmmap()などのメモリ割り当て関数は、割り当て中にプロセス仮想アドレススペースを確立するだけであり、仮想メモリに対応する物理メモリを割り当てません。プロセスがマッピング関係を確立していないこれらの仮想メモリにアクセスすると、プロセッサは自動的にページ障害例外をトリガーします。
ページ障害割り込み:要求ページングシステムでは、ページテーブルのステータスビットをチェックして、アクセスするページがメモリに存在するかどうかを判断できます。アクセスするページがメモリにない場合は、ページ障害割り込みが発生します。このとき、オペレーティングシステムは、ページテーブルの外部メモリアドレスに従って、外部メモリで欠落しているページを検出し、メモリに転送します。
ページ障害自体は中断です。一般的な中断と同様に、次の4つの処理手順を実行する必要があり
ます。1。CPUサイトを保護する
2.中断の原因を分析する
3.処理のためにページ障害中断ハンドラーに転送する
4. CPUサイトを復元し、実行を続行する
ただし、ページ障害割り込みは、アクセスするページがメモリに存在しない場合にハードウェアによって生成される特殊な割り込みであるため、一般的な割り込みとは異なり
ます。1。ページ障害割り込み信号は、命令
2の実行中に生成および処理されます。命令の実行中に、複数のページ障害割り込みが生成される場合があります。3。
ページ障害割り込みリターンは、割り込みを生成する命令を実行することであり、一般的な割り込みリターンは、次の命令を実行することです。
[クリックしてグループチャット学習交換グループに参加]

おすすめ

転載: blog.csdn.net/weixin_52622200/article/details/110656753