1. はじめに
データ構造では、主に非数値計画法に現れるコンピュータの演算対象とそれらの関係や動作などを研究します。
用語
データ( Data ):情報とは、 コンピューターサイエンスにおいて、コンピューターに入力され、コンピュータープログラムによって処理されるすべてのシンボルの総称を指します。
例えば、客観的な物事の記号表現において、構造においては、その構造に描かれている内容がデータである
データ要素( Data Element ) : データの基本単位
データ項目( Data Items ) :データ要素を構成する独立した意味を持つ最小単位です。
データ要素には 1 つまたは複数のデータ項目を含めることができます。たとえば、データベース テーブルの列はデータ項目であり、各行はデータ要素です。
通常、計算プログラムではデータの基本単位を全体として考えて処理しますが、本の番号情報がデータ要素、書誌情報がそれぞれデータ要素であるなど、データ要素が複数のデータ項目から構成される場合もあります。 item(書名、著者名など)はデータ項目であり、データ項目はデータの最小単位であり、配列int a[10]には10個の要素があり、全体の構造がデータ要素となります
データ オブジェクト( Data Object ) :要素のコレクション
これは、同じ性質を持つデータ要素の集合であり、
整数データ オブジェクト N = {0, ±1, ±2, ±3, ...}、アルファベット文字データ オブジェクト C = { などのデータのサブセットです。 'A'、'B'、'C'、...、'Z'}
データ構造(データ構造) :
これは、データ要素間に 1 つ以上の特定の関係があるデータ要素のコレクションです (通常、基本構造は 4 種類あります)。
Set : 構造内のデータ要素には、「同じセットに属する」という関係以外の関係はありません。
線形構造: 構造内のデータ要素間には 1 対 1 の関係があり、 最初の要素を除く他の要素には 1 つの先行要素があり、最後の要素を除く他の要素には 1 つの後続要素しかありません。
ツリー構造: 構造内のデータ要素間には 1 対多の関係があります 。つまり、要素には先行要素が 1 つだけありますが、複数の後続要素を持つことができます。
グラフまたはネットワーク構造: 構造内のデータ要素には多対多の関係があり、 要素間の論理関係は任意です。
上記のことから、データ構造は構造を持つデータ要素の集合であることが わかります。
データ構造の 3 つの要素
(1)論理構造:データ間の関係の記述、仮想
論理構造の形式では、2 つのタプルが使用されます。B= ( K, R ) 、Kはノードのセット、RはKに関するリレーションのセットです。たとえば、 < k, k ' >は、 kが先行することを意味しますk'の、k 'はkの後継、隣接ノードの論理構造は ストレージ構造から独立しており、ストレージ構造は論理構造に依存します
(1.1) 線形構造:開始ノードと終端ノードが 1 つだけあり、すべてのノードには最大 1 つの直接の先行ノードと 1 つの直接の後続ノード ( 1 to 1 )があります。典型的な例は次のとおりです: 線形リスト、スタック、キュー、配列、弦
(1.2) 非線形構造:各ノードは複数の直接の先行ノードと直接の後続ノード( 1対1ではない) 、典型的なツリー、グラフ、セットを持つことができます。
(2) 記憶構造:コンピュータ内にマッピングされたデータ構造を記憶構造といい、実際のデータ構造は
記憶構造は論理関係のイメージと要素自体のイメージであり、記憶構造は本質的にメモリ割り当てです。
注: コンピュータに情報を保存する最小単位はビット (ビット) と呼ばれ、8 ビットはバイト (バイト) を表し、2 バイトはワード (ワード) と呼ばれ、バイト、ワード、またはそれ以上のバイナリ ビットを と呼びます。要素またはノードと呼ばれるビット列。データ要素が複数のデータ項目で構成されている場合、ビット列内の各データ項目に対応するサブビット列をデータフィールドと呼びます。
(2.1)シーケンシャルストレージ構造(シーケンシャルストレージ構造):論理的に接続されたノードを物理的に隣接するストレージ装置に格納し、ノード間の論理関係がストレージ装置の隣接関係に反映される。一般的には配列や構造体配列で記述します。
(2.2)リンクストレージ構造(LinkedStorage構造):論理的に隣接するノードを必要とせず、それらは物理的に隣接し、ノード間の論理関係は追加の(ポインタ)参照フィールドによって表される。ノードの参照フィールドは、多くの場合、次のノードの格納場所をガイドします。通常、リンクリストは説明に使用されます。
(2.3) インデックス格納方式 (index ) : インデックス格納方式は、追加のインデックステーブルを使用してノード情報を格納する格納方式です。インデックス テーブルは、複数のインデックス エントリで構成されます。インデックス ストレージ モードにおけるインデックス項目の一般的な形式は(キーワード, アドレス)です。このうちキーとは、ノードを一意に識別できるデータ項目である。
(2.4) ハッシュ保存方法 (ハッシュ) :ノードのキーワードに従ってハッシュ関数を通じてノードの保存アドレスを直接計算します。
(3) データ計算:一部の操作、追加、削除、変更、確認
データ型(データ型) : type
値の集合と、その値の集合に対して定義された演算の集合(例えば、値の集合が一定区間の整数であるC言語の整数変数)の総称であり、その値の集合に対して定義された演算は加算である。 、減算、乗算などのデジタル演算やアナログ演算などの算術演算)、「値」のさまざまな特性に応じて、高級プログラミング言語のデータ型は 2 つのカテゴリに分類できます
非構造アトミック タイプ: アトミック タイプは分解できません。例: C の基本タイプ (整数、実数、文字、および列挙タイプ)、ポインタ タイプ、および空のタイプ。
構造型: 構造型の値は、特定の構造に従って複数のコンポーネントで構成されているため、分解することができ、そのコンポーネントは非構造または構造にすることができます。例: 配列の値は複数のコンポーネントで構成されます、各 A コンポーネントは整数、配列などにすることができます。ある意味、データ構造は「同じ構造を持つ値のグループ」とみなすことができ、データ構造はデータとみなすことができます。構造体とそれに定義された一連の操作が構成されます。
抽象データ型 (Abstract Data Type、ADT) : 数学的モデルとそのモデルに定義された一連の操作を指します。抽象データ型の定義は、その内部表現や実装ではなく、論理特性のセットにのみ依存します。コンピュータ 無関係、つまり、内部構造がどのように変化しても、数学的特性が変わらない限り、外部での使用には影響しません。
抽象データ型(抽象データ型、ADT ) :モデル、タイプ
抽象データ型を含むソフトウェア モジュールは、通常、「定義、表現、実装」の3 つの部分
で構成されます。抽象データ型の定義は、値の範囲と、その値の範囲内で定義された一連の操作で構成されます。その価値は3つのタイプに分けられます
アトミック データ型(アトミック データ型) アトミック型に属する変数の値は分解できません。一般に、既存の固有のデータ型で要件を満たすのに十分であるため、このような抽象データ型は少なくなりますが、場合によっては要件を満たすことができません。新しい原子を定義するために必要なデータ型。全桁が 100 の整数など。
構造タイプ
固定集計データ型(固定集計データ型) はこの型の変数であり、その値は特定の構造内の特定の数の成分で構成されます。たとえば、複素数は特定の 2 つの実数で構成されます。順序関係。
可変集合日付型(可変集合日付型)は、固定集合型と比較して、可変集合型の「値」を構成する要素の数が不明確です。例えば、「順序付き整数」の抽象データ型は、シーケンス」を定義でき 、固定集計タイプと可変集計タイプを総称して、
多態性データ型(ポリモーフィックデータ型)とは、値の構成が不確実なデータ型のことをいい、抽象データ型では、要素がどのような特性を持っていても、要素間の関係は同じであり、基本的な動作も同じです。 . 抽象データ型から 観点から見ると、同じ数学的抽象化特性を備えているため、多態性データ型と呼ばれます。
2. アルゴリズム
1.コンセプト
アルゴリズム +データ構造=プログラム。データ構造とアルゴリズムはプログラムの 2 つの主要な要素であり、この 2 つは相互に補完し合い、不可欠であることを示しています。アルゴリズムはプログラムの魂です。
アルゴリズム: アルゴリズムとは、問題を解決するための方法またはプロセスです。
プログラム: プログラムは、プログラミング言語でのアルゴリズムの具体的な実装です。
アルゴリズムとプログラムはどちらも問題を解決するための論理的な手順を表現するために使用されますが、アルゴリズムは特定のコンピューターから独立しており、特定のプログラミング言語とは何の関係もありませんが、プログラムはその逆であり、プログラムはアルゴリズムですが、アルゴリズムは必ずしもプログラムであるとは限りません。
2. アルゴリズムの特徴
有限性: アルゴリズムは有限数のステップを実行した後に終了する必要があり、各ステップは有限時間内に完了する必要があります。
決定性: アルゴリズムの各ステップの意味は決定的である必要があり、曖昧であってはなりません。
入力: アルゴリズムには 0 個以上の入力を含めることができます。
出力: アルゴリズムには 1 つ以上の出力があります。
実現可能性: アルゴリズムは実現可能でなければなりません。つまり、アルゴリズム内の各操作は、既知の基本操作のセットによって実現できます。
データ構造(記憶構造)の表現は、型定義(typedef)によって記述されます。データ要素の型規則は ElemType です。
3. 時間計算量
アルゴリズムの実行時間:アルゴリズムの実行時間は、そのすべてのステートメントの実行時間の合計にほぼ等しくなります。ステートメントの実行時間は、ステートメントの実行時間と 1 回の実行に必要な時間の積を指します。
ステートメント頻度:アルゴリズム内でステートメントが繰り返し実行される回数を指します。アルゴリズム内のすべてのステートメント頻度の合計はT(n)として記録され、基本演算頻度はf(n) 、 T(n)となります。 =O(f( n))は、問題スケールn が増加するにつれて、アルゴリズムの実行時間の増加率がf(n)の増加率と同じになることを意味します。これは、アルゴリズムの漸近時間計算量と呼ばれます、または略して時間計算量。つまり、時間計算量はカウント頻度と同じです。
時間計算量は、実行ステートメントが呼び出される回数です。
時間計算量は問題のサイズとデータの初期状態によって異なります。
T(n)=O(f(n))で最も速い成長率を持つ項目を選択し、係数を1として記述する必要があります。 f(n) が n と関係がない場合、つまり、周波数は定数です。、つまり明確に表現できる数字の場合は、O (1)と書きます。
最悪時間計算量と平均時間計算量 最悪の場合の時間計算量を最悪時間計算量と呼びます。一般に特に指定されていませんが、ここで説明する時間計算量は最悪の場合の時間計算量です。その理由は、最悪の場合の時間計算量は、入力インスタンスでのアルゴリズムの実行時間の上限であり、アルゴリズムの実行時間がどの入力インスタンスよりも長くならないことが保証されるためです。
ルール
T(n)=T1(n)+T2(n)=O(f(n)+g(n))=O( max (f(n),g(n))
T(n)=T1(n)*T2(n)=O(f(n)*g(n))=O (f(n)*g(n))
最も深いループにおけるステートメントの頻度の一般的な計算は、時間計算量です。
一般的な時間計算量
常用的时间复杂度:O(1) <O(log2n) < O(n) < O(n log2n) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
時間計算量の計算方法
(1) x=5;
if(x<-4)
{x=x+4;}
else
{x=x+3;}のように 1 回だけ呼び出される場合
、ステートメントは 1 回だけ呼び出されます。 then O(n)=1;
(2) 次のように 2 回呼び出された場合:
x=5;
if(x<-4)
{x=x+4;}
else
{x=x+3;}
x =x+ 56;
中括弧内の内容はステートメントを 1 つだけ呼び出しますが、最後にステートメントを呼び出すための計算式がまだあり、合計で 2 回呼び出されます。次に、O(n)=2;
(3) FOR ループ
を使用してfor(x=0;x<n;x++)
{x=x+1;}を呼び出します
。x は 0 から n-1 までループし、ステートメント 現在の x 値を新しい x に追加し、合計で n 回呼び出すことです; then O(n)=n; (
4) 2 つのネストされたFOR ループ
を使用してfor(x=0;x<n;x++ を呼び出します) )
{ for( y=1;y<=n;y++) {x=x+y;} }
ネストされたループが発生した場合は、主に内側の FOR ステートメントの時間計算量に応じて、まず外側の FOR ステートメントの変数を初期値 x=0 に修正します。明らかに、内側のステートメントの実行回数は 1 から 1 までです。 n を合計 n 回呼び出すと、O(n)=n になります。これは x=0 の場合のみの呼び出しです。x は 0 から n-1 まで、合計で n 回変化します。各呼び出しでは y への呼び出しが n 回実行されるため、ステートメント x=x+y が実行され、合計で n*n 個の呼び出しが行われます。O(n)=n^2。
実行文の実行回数が時間計算量となる。注:
(1) 正しい実行ステートメントを見つけます。
(2) for ループの初期値と終了値。
for(i=0;i<n;i++) i の値は 0 から n-1 まで、合計 n 回変化します。
for(i=0;i<=n;i++) i の値は 0 から n まで、合計 n+1 回変化します。
(3) for ループの呼び出し順序に注意してください。内側から外側に向かっていきます。
注: i 番目のノードへの訪問はランダムであり、時間計算量は o(1)、移動する必要のないものは o(1)、移動する必要があるものは o(n) です。
4. 空間の複雑さ
アルゴリズムの記憶域要件に関しては、アルゴリズムの時間計算量と同様に、アルゴリズムが必要とする記憶域の尺度 S として空間計算量を使用します。これは次のように記録されます。 S(n)=O( f ( n)) 、ここでnは問題の規模、Oは大きさの桁を意味します。
入力データが占める特定のストレージ量は問題自体にのみ依存し、アルゴリズムとは関係がないため、アルゴリズムの実装に必要な補助スペースのみを分析する必要があります。必要な補助空間が入力データに対して一定である場合、アルゴリズムは適切に機能すると言われ、補助空間はO(1)です。
3. リニアテーブル
1. 定義
線形リスト( Linear_List )は、略してリストと呼ばれます。同じタイプのデータ要素のn ( n≥0 )個の有限シーケンス です。ここで、n はリストの長さであり、n=0 の場合、線形リストは次のようになります。空のリスト。線形テーブルの名前に L を使用する場合、一般的に次のように表されます。 L=(a1, a2, ..., ai, ai+1, ..., an)
線形テーブルは、最も単純かつ基本的で、最も一般的に使用される線形構造です (線形構造は、データ要素間の線形関係によって特徴付けられます)。シーケンシャル構造のストレージとチェーン構造のストレージがあり、主な基本操作としては挿入、削除、検索などが挙げられます。線形テーブルでは、データ要素のタイプが同じであるか、または線形テーブルは同じタイプのデータ要素で構成される線形構造です。
線形テーブルの長さ: 線形テーブル内のデータ要素の数
空のリスト:長さがゼロに等しい線形リスト
最初の要素を除くすべての要素には、直前の先行要素が 1 つだけあります。
最後を除くすべての要素には、直接の後続要素が 1 つだけあります。
2. 特徴
恒等性: 線形テーブルは類似のデータ要素で構成されており、各a i は同じデータ オブジェクトに属している必要があります。
有限性: 線形テーブルは有限数のデータ要素で構成され、テーブルの長さはテーブル内のデータ要素の数になります。
Order : 線形テーブル<a i , a i +1>内の隣接するデータ要素間には偶数の順序関係があります。
- テーブル内の要素の数には制限があります。
- テーブル内の要素には論理的な順序があり、シーケンス内の各要素の順序には独自のシーケンスがあります。
- テーブル内の要素はすべてデータ要素であり、各テーブル要素は単一の要素です。
- テーブル内の要素のデータ型はすべて同じです。これは、各テーブル要素が同じ量の記憶領域を占有することを意味します。
一意の最初の要素、一意の最後の要素、最初の要素を除くすべての要素には先行要素があり、最後の要素を除くすべての要素には後続要素があり、各要素にはビット順序があります
注: 注: 線形リストは、要素間の 1 対 1 の隣接関係を表す論理構造です。シーケンス リストとリンク リストは、異なるレベルの概念に属する ストレージ構造を指すため、混同しないでください。
3. 線形テーブル順次ストレージ
線形テーブルのシーケンシャル ストレージ(シーケンシャル マッピング、シーケンシャル テーブルと呼ばれる) : 連続したアドレスを持つストレージ ユニットのグループを使用して、線形テーブル内の各要素を順番に格納することを指します。線形テーブルは物理記憶装置に隣接して格納されます。
C言語の1次元配列はメモリ上の連続したアドレスの記憶領域を占有する ため、シーケンシャル記憶の核となるのは配列です。
順次記憶構造を持つ線形テーブルは、通常、順次テーブルと呼ばれます。
線形テーブルに n 個の要素があり、各要素がk単位 (バイト)を占め、最初の要素のアドレスがloc(a1)であると仮定すると、i番目の要素のアドレスloc(a i )を計算できます。
場所(ai) = 場所(a 1 )+(i-1)×k
ここで、loc(a 1 ) はベースアドレスと呼ばれます。要素のシリアル番号と配列の添字を区別します。たとえば、 1のシリアル番号は1で、それに対応する配列の添字は0です。
シーケンステーブルの特徴:ランダムアクセス、検索時間計算量O(1)、多数の要素の削除、挿入、移動
シーケンステーブル構造の説明
構造体の型の宣言:
typedef 構造体リスト
{
ElemType data[MAXSIZE]; //配列にはデータ要素が格納されます
int length; //線形テーブルの現在の長さ
SqList , *リスト;
注: シーケンス テーブルの操作
int isEmpty(SqList &L);//判断表是否为空
int getElem(SqList L, int i);//返回第i个位置的值
int listInsert(SqList &L, int i, int e);//在指定位置第i处插入数据e
int listDelete(SqList &L, int i);//删除指定位置的元素
void printList(SqList &L);//打印线性表
int listLength(SqList &L);//求线性表的长度
void initList(SqList &L);//初始化线性表
int locateElem(SqList &L, int x)//返回该值的位置
int destroylist(sqlist &l)//销毁链表
4. シーケンステーブルの動的割り当て
静的に割り当てられたシーケンス テーブルのメモリは固定されており、メモリ割り当てが少なく、オーバーフローしやすく、メモリ割り当てが増えるとメモリが無駄になるため、動的に割り当てるのが最善ですが、それでもリンク リストではなくシーケンス テーブルに属します。
malloc()関数は、メモリ空間を動的に割り当てるために使用されます。
注: 静的割り当ての解放はプログラムによって決定され、メモリは main 関数の実行後にのみ解放されます。
動的割り当てのリリースは手動でリリースされ、キーワードは free (パラメータ) です。
realloc() 関数はメモリ空間の再割り当てに使用され、そのプロトタイプは次のとおりです:
void* realloc (void* ptr, size_t size);
【パラメータの説明】 ptr は再割り当てするメモリ空間のポインタ、size はメモリ空間のサイズです。新しいメモリ空間。
realloc() は、ptr が指すメモリに size のスペースを再割り当てします。サイズは元のサイズより大きくても小さくてもよく、変更されないままにすることもできます。malloc()およびcalloc()によって割り当てられたメモリ空間 が十分でない場合 、realloc() を使用して割り当てられたメモリを調整できます。
ptr が NULL の場合、その効果は malloc() と同じです。つまり、size バイトのメモリ空間を割り当てます。size の値が 0 の場合、 ptr が指すメモリ空間は解放されますが、新しいメモリ空間は開かれていないため、 free()
を呼び出した場合と同様に null ポインタが返されます 。
注意すべき点がいくつかあります:
- ポインタ ptr は、動的メモリ空間に正常に割り当てられたポインタである必要があります。次の形式のポインタは許可されません: int *i; int a[2]; 実行時エラーが発生します。次のように覚えてください: malloc()、calloc()、realloc() を使用します。 正常に割り当てられたポインタは、realloc() 関数で受け入れることができます。
- メモリの割り当てが成功すると、ptr はシステムによって再利用されるため、free() を含め、ptr ポインターに対して操作を実行してはなりません。逆に、realloc() 関数の戻り値に対して通常の操作を実行できます。
- 操作がメモリを拡張する場合、ptr が指すメモリ内のデータは新しいアドレスにコピーされます(新しいアドレスは元のアドレスと同じである可能性もありますが、元のポインタに対して操作を実行することはできません)。 ; メモリを縮小する操作の場合、元のデータは削除されます。コピーして新しい長さに切り詰めます。
【戻り値】 割り当てが成功すると、新しいメモリアドレスが返されます。ptr と同じか異なる場合があり、失敗した場合は NULL を返します。
注: 割り当てが失敗した場合、ptr が指すメモリは解放されず、その内容は変更されず、引き続き通常どおり使用できます。
補足:参考文献の使い方
参照は変数 (ターゲット) のエイリアスであり、参照に対する操作は変数に対する直接操作とまったく同じです。同一の記憶装置に属する
参照宣言方法:型識別子&参照名=対象変数名;
【例1】: int a; int &ra=a; //変数aの参照である参照ra、つまりエイリアスを定義 解説: (1) ここでの&はアドレス計算ではなく
識別
です。
(2) 型識別子は、ターゲット変数の型を指します。
(3)参照を宣言するときは、同時に初期化する必要があります。
(4)参照宣言が完了すると、対象変数名は対象元の名前と参照名の2つの名前を持つことになり、参照名を他の変数名の別名として使用することはできません。
ra=1; は a=1; と同等です
(5) 参照の宣言は新しい変数を定義するのではなく、参照名がターゲット変数名のエイリアスであり、それ自体はデータ型ではないことを意味するだけです。参照自体 ストレージユニットが占有されておらず、システムは参照用にストレージユニットを割り当てません。したがって、参照のアドレスを見つけることは、ターゲット変数のアドレスを見つけることと同じです。&ra は &a と同じです。
(6)配列への参照が確立できません。配列は複数の要素のコレクションであるため、配列のエイリアスを作成することはできません。
参照アプリケーション
1. パラメータとしての参照
重要な参照機能は、関数のパラメータとしての参照です。以前は、C 言語での関数パラメータの受け渡しは値の受け渡しでした。大きなデータ ブロックがパラメータとして渡される場合は、データ ブロック全体をスタックにプッシュすることを回避し、関数の効率を向上させることができるため、ポインタがよく使用されました。プログラム。しかし、現在 (C には) 同様に効率的なオプション (特殊な場合には必要なオプション)、つまり参照が存在します。
(1) 関数への参照を渡すことは、ポインタを渡すことと同じ効果があります。このとき、呼び出される関数の仮パラメータは、元の呼び出し関数の実パラメータ変数またはオブジェクトのエイリアスとして使用されるため、呼び出される関数の仮パラメータ変数に対する操作は、対応するターゲット オブジェクト(メインでは関数の呼び出し) 関数の呼び出し) 操作。
(2)関数のパラメータは参照によって渡され、実パラメータのコピーはメモリ内に生成されず、実パラメータに対して直接操作されますが、関数のパラメータは一般変数によって渡されます。関数呼び出しが発生すると、ストレージを仮パラメータ Unit に割り当てる必要があり、仮パラメータ変数は実際のパラメータ変数のコピーです。オブジェクトが渡されると、コピー コンストラクタも呼び出されます。したがって、パラメーターによって渡されるデータが大きい場合、参照によって占有される効率とスペースは一般変数よりも優れています。
(3)関数の引数としてポインタを使用することでも参照を使用する効果が得られますが、呼び出される関数では仮引数にも記憶装置を割り当て、「*ポインタ変数名」の形式で演算する必要があります。を繰り返す必要があります。これではエラーが発生しやすく、プログラムの可読性も悪くなります。一方、呼び出し関数の呼び出し点では、変数のアドレスを実パラメータとして使用する必要があります。一方、リファレンスは使いやすく、より明確です。
参照を使用してプログラムの効率を向上させ、関数に渡されたデータが関数内で変更されないように保護する場合は、定数参照を使用する必要があります。
2. 共通
参照 共通参照の宣言方法: const 型識別子 & 参照名 = 対象変数名;
このように宣言された参照は、参照によって対象変数の値を変更できないため、参照の対象が const となり引用が達成されます。安全。
その理由は、foo() 文字列と「hello world」文字列の両方が一時オブジェクトを生成し、C ではこれらの一時オブジェクトが const 型であるためです。したがって、上記の式は const 型のオブジェクトを非 const 型に変換しようとしていますが、これは不正です。
参照パラメータは、const で定義できるものであれば、可能な限り const で定義する必要があります。
3. 戻り値としての
参照 関数の値を参照で返すには、関数定義は次の形式に従う必要があります。
型識別子 & 関数名 (仮引数リストと型の説明)
{関数本体}
説明:
(1)関数の値を返す参照、関数を定義するときは、関数名の前に & を追加する必要があります
(2)関数の値を参照によって返す最大の利点は、戻り値のコピーがメモリに生成されないことです。
戻り値としての参照は以下の規則に従う必要があります。
(1) ローカル変数への参照は返せません。この記事は、Effective C [1] の項目 31 を参照できます。主な理由は、関数が戻った後にローカル変数が破棄されるため、返された参照が「何もない」参照になり、プログラムが不明な状態になることです。
(2) 関数内で new で確保したメモリへの参照は返せません。この記事は、Effective C [1] の項目 31 を参照できます。ローカル変数の受動的破壊の問題はありませんが、この状況 (関数内で new によって割り当てられたメモリへの参照を返す) では、別の厄介な状況に直面します。たとえば、関数によって返される参照は、実際の変数が割り当てられずに一時変数としてのみ表示されます。その場合、参照が指す領域 (new によって割り当てられた) を解放できず、メモリ リークが発生します。
(3) クラス メンバーへの参照を返すこともできますが、できれば const を返します。この原則は、有効 C [1] の項目 30 を参照できます。主な理由は、オブジェクトの属性が特定のビジネス ルールに関連付けられている場合、その割り当てが他の属性やオブジェクトの状態に関連していることが多いため、割り当て操作をビジネス ルールにカプセル化する必要があるためです。他のオブジェクトがプロパティへの非 const 参照 (またはポインタ) を取得できる場合、プロパティへの単なる割り当てはビジネス ルールの整合性を損なうことになります。
4. 参照とポリモーフィズム
参照は、ポリモーフィック効果を生み出すことができるポインター以外のもう 1 つの手段です。これは、基本クラスへの参照がその派生クラスのインスタンスを指すことができることを意味します。
[例7]:
class A;
class B: public A{...};
B b;
A &Ref = b; // 派生クラスオブジェクトを使用して参照を初期化
基本クラスオブジェクトのRefはアクセスのみに使用可能基本からの派生クラス オブジェクト クラスから継承されたメンバーは、派生クラスを指す基本クラス参照です。クラス A で定義された仮想関数があり、この仮想関数がクラス B で書き換えられる場合、Ref を介してポリモーフィック効果を生成できます。
リファレンスのまとめ
(1) リファレンスの利用においては、単に変数にエイリアスを与えるだけでは意味がありません リファレンスの目的は、主に関数パラメータの転送において、転送効率が悪い、大きなブロックの容量の問題を解決するために使用されます。データまたはオブジェクトに関する質問。
(2) 関数のパラメータを参照渡しすることで、パラメータ転送時にコピーが生成されず転送効率が向上するとともに、const を使用することで参照転送の安全性が保証されます。
5. リンクリスト
- ヘッド補間: 挿入順序はリンク リストの順序と逆になります。
- 末尾挿入方式: 挿入順序はリンクリストの順序と同じです
( 1) 特徴
論理的順序と物理的順序は必ずしも同じではなく、物理メモリはポインタで表現される要素間の連続した論理関係を必要としません
(2) ノード
ノード間の論理関係を正確に表現するためには、線形テーブルに各データ要素の値を格納するとともに、その後継ノードを示すアドレス(または位置)情報も格納する必要があり、この2つの情報からなる格納イメージは、ノードと呼ばれます。
(3) 単一リンクリスト
単一リスト