目次
上記は線形表の学習に関する私の個人的な意見と分析です。コメント欄での議論を歓迎します。
ワンクリック3接続の皆さん、ありがとうございます!ワンクリック3接続の皆さん、ありがとうございます!ワンクリック3接続の皆さん、ありがとうございます!
スタック:
スタックの概念と構造:
スタック:固定端の要素の挿入と削除のみを許可する特別な線形リスト。データの挿入および削除操作が実行される端をスタックの最上位と呼び、もう一方の端をスタックの最下位と呼びます。スタック内のデータ要素は、LIFO (Last In First Out) の原則に従います。一般に、1. フェアネス キューイング (数値描画マシン)、2. BFS (幅優先トラバーサル) で使用されます。
スタックのプッシュ: スタックの挿入操作はプッシュ/プッシュ/プッシュと呼ばれ、受信データはスタックの先頭にあります。
ポッピング: スタックの削除操作はポッピングと呼ばれます。出力データもスタックの最上位にあります。
スタックの実装:
スタックの実装は通常、配列またはリンク リストを使用して実装できますが、比較的に配列の構造の方が優れています。配列の最後にデータを挿入するコストが比較的小さいためです。チェーンの末尾挿入ではより多くのデータを動員する必要があり、そのプロセスでより多くのデータが消費されます。
// 動的に成長するスタックをサポートtypedef int STDataType ;typedef 構造 体スタック{STDataType * _a ;int _top ; // スタックの先頭int _capacity ; // 容量スタック ; _// スタックを初期化しますvoid StackInit ( Stack * ps );// スタックにプッシュするvoid StackPush ( Stack * ps , STDataType データ );// 飛び出すvoid StackPop ( Stack * ps );// スタックの最上位要素を取得しますSTDataType StackTop ( Stack * ps );// スタック内の有効な要素の数を取得しますint StackSize ( Stack * ps );// スタックが空かどうかを確認し、空の場合は 0 以外の結果を返し、空でない場合は 0を返します。int StackEmpty ( Stack * ps );// スタックを破棄しますvoid StackDestroy ( Stack * ps );
//スタックを初期化する
//初始化
void SLInit(SL* ps)
{
assert(ps);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
//スタックにプッシュする
//入栈
void SLPush(SL* ps, STDataType x)
{
assert(ps);
//栈顶=容量说明需要扩容
if (ps->capacity == ps->top)
{
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->capacity = newcapacity;
ps->a = tmp;
}
ps->a[ps->top] = x;
//后缀++方便下一次入栈和打印栈顶
ps->top++;
}
// 飛び出る
//出栈
void SLPop(SL* ps)
{
assert(ps);
//为空情况“0”
assert(ps->top > 0);
//
--ps->top;
}
// スタックの最上位要素を取得します
//获得栈顶元素
STDataType SLTTop(SL* ps)
{
assert(ps);
//为空情况“0”
assert(ps->top > 0);
int n = (ps->top) - 1;
return ps->a[n];
}
// スタック内の有効な要素の数を取得します
//获取栈中有效元素个数
int SLSize(SL* ps)
{
assert(ps);
return ps->top;
}
//スタックを破棄する
//销毁栈
void SLDestroy(SL* ps)
{
assert(ps);
//开辟数组优势:一次全部释放
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
// スタックが空かどうかを確認し、空の場合は 0 以外の結果を返し、空でない場合は 0 を返します。
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool SLEmpty(SL* ps)
{
assert(ps);
//为“0”说明为NULL
if (ps->top == 0)
{
return true;
}
return false;
}
列:
キューの概念と構造:
キューの実装:
キューは配列やリンク リストの構造でも実装できますが、配列の構造を使用すると、配列の先頭にあるデータのデキューと出力の効率が相対的に高くなるため、リンク リストの構造を使用することをお勧めします。低い。
// チェーン構造: キューを表しますtypedef 構造体 QListNode{struct QListNode * _pNext ;QDataType _data ;QNode ; _// キューの構造typedef 構造 体キュー{QNode * _front ;QNode * _rear ;キュー ; _// キューを初期化しますvoid QueueInit ( Queue * q );// キューの最後がキューに入るvoid QueuePush ( Queue * q , QDataType data );// キューの先頭がキューから外れましたvoid QueuePop ( Queue * q );// キューの先頭の要素を取得しますQDataType QueueFront ( Queue * q );// キューの末尾要素を取得しますQDataType QueueBack ( Queue * q );// キュー内の有効な要素の数を取得しますint QueueSize ( Queue * q );// キューが空かどうかを確認し、空の場合は 0 以外の結果を返し、空でない場合は 0を返します。int QueueEmpty ( Queue * q );// キューを破棄するvoid QueueDestroy ( Queue * q );
//初期化
//初始化
void QueueInit(Que* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
//エンキュー
//入列
void QueuePush(Que* pq, Qdatatype x)
{
assert(pq);
//开辟队列结构动态内存
Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
//第一次或N+1次
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
// デキュー
//出列
void QueuePop(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
if (pq->head->next == NULL)
{
//就剩下一个
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
//剩下两个及以上
Que * del = pq->head;
pq->head = pq->head->next;
free(del);
}
pq->size--;
}
// キューの先頭の要素を取得します
// 获取队列头部元素
Qdatatype QueueFront(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
// キューの末尾要素を取得します
// 获取队列队尾元素
Qdatatype QueueBack(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
// キュー内の有効な要素の数を取得します
// 获取队列中有效元素个数
int QueueSize(Que* pq)
{
assert(pq);
return pq->size;
}
// キューが空かどうかを確認し、空の場合は 0 以外の結果を返し、空でない場合は 0 を返します。
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Que* pq)
{
assert(pq);
return pq->head == NULL;
}
//破壊する
//销毁
void QueueDestroy(Que* pq)
{
assert(pq);
while (pq->head)
{
Que* del = pq->head->next;
free(pq->head);
pq->head = del;
pq->size--;
}
pq->head = pq->tail = NULL;
}
拡張された知識:
キューは、リンク リストを使用した実装に適しています。逐次構造 (つまり、固定された連続スペース) を使用すると、誤ったオーバーフローの問題が発生します。そのため、大手企業は循環キューを設計しました。循環キューは、誤ったオーバーフローの問題を解決するように設計されています。連続した構造。
循環キュー:実際には、循環キューと呼ばれるキューが使用されることがあります。たとえば、オペレーティング システムのコースで生産者/消費者モデルを説明する場合、循環キューを使用できます。循環キューは、配列または循環リンク リストを使用して実装できます。
同時に空いている位置を指し、後ろ(尻尾)の次の位置が前(頭)になると埋まったことを意味し、埋まっているかどうかを判断するための余分なスペースがここにあります。ない!!!
上記は線形表の学習に関する私の個人的な意見と分析です。コメント欄での議論を歓迎します。
ワンクリック3接続の皆さん、ありがとうございます!ワンクリック3接続の皆さん、ありがとうございます!ワンクリック3接続の皆さん、ありがとうございます!