質問を確認して面接するときは、リンクリストなどの質問に常に遭遇します。Leetcodeの質問を見てみましょう。
1.リンクリストとは何ですか?
各データ要素を表すためにaia_ia私直接の後継データではなくai + 1 a_ {i + 1}aI + 1間の論理関係、データai a_ia私つまり、独自の情報を格納するだけでなく、後続情報の表示(つまり、直後の後続情報の格納場所)も格納する必要があります。要素データを格納するドメインをデータドメインと呼び、直後の後続位置に格納されるドメインをポインタドメインと呼びます。ポインタフィールドに格納されている情報は、ポインタまたはチェーンと呼ばれます。データ要素aia_iで構成されるこの2部構成のメッセージa私ストレージイメージはノードと呼ばれます。
リンクリストの場合、ヘッドノードはオプションです。ヘッドノードは、単一リンクリストの最初のノードの前に表示され、リンクリストの追加情報(長さなど)を提供するために新しいノードを追加します。
リンクリストにはヘッドノードを含めることはできませんが、ヘッドポインターが必要であるため、リンクリストの名前は通常ヘッドポインターで表されます。ヘッドノードの役割:
- リンクリストを削除および挿入する場合、最初のノードの操作がより便利です
- 空のリストと空でないリストの統合処理
具体的な説明については、https://blog.csdn.net/snow_7/article/details/106919353をご覧ください。
ポインタドメインによると、単一リンクリストと呼ばれるものは1つだけです。このセクションでは、単一リンクリストのみを紹介します。後で、循環リンクリストと二重リンクリストを紹介します。
第二に、ノードの構造
この構造を実装するためにポインタを使用します。この構造には、ポインタフィールドとデータフィールドの少なくとも2つの部分が含まれています。
typedef struct Node{
int data;
struct Node* next;
}Node;
typedef struct Node* pNode;//指向一个结点的指针
非常に重要です!!!!追加のヘッドノードがないリンクリストの場合、ヘッドポインターは、リンクリストの最初のノードを指します。追加のヘッドノードがあるリンクリストの場合、ヘッドポインターは、この追加のヘッドノードを指します。質問を書くときに追加のヘッドノードがないようです。ヘッドノードが空を指している場合、リンクリストの長さは0、つまり空のリンクリストです。ヘッドノード-> nextが空の場合、リンクリストの長さは1です。ヘッドノードは最初のノードと同じではなく、最初のノードの前のノードです。
三、価値
//pHead在这里是一个指向头结点或者第一个结点
bool get_index_element(pNode pHead, int i, int* value)
{
int j = 1;//用于标识当前检查的结点号
pNode pCurNode = pHead->next;//j=1,cur指向结点1
//进入循环的条件:没有达到链表最后结点或者还没检查到指定序号结点或给了一个比1还要小的检查序号
while (pCurNode &&j<i)
{
//更新序号和待检查结点指针pCurNode
j++;
pCurNode = pCurNode->next;
}
//若到达最后了仍然没有找指定序号结点,那么说明长度不够,返回false
//或者是用户给了一个不正确的序号参数(i<1)
if (!pCurNode && i < j)
{
return false;
}
*value= pCurNode->data;
return true;
}
PS:curポインターがnullポインターの場合、暗黙的にfalseに変換されます。それ以外の場合はtrueに変換されます。
第四に、要素の前に挿入します
選択した要素が新しい要素に従って挿入される前または後
bool insert_index_element(pNode * pHead,int i,int value)
{
int j = 1;
pNode pCurNode = pHead->next;
while (pCurNode || j < i)
{
pCurNode = pCurNode->next;
j++;
}
if (!pCurNode && i < j)
{
return false;
}
pNode pNewNode = (pNode)malloc(sizeof(Node));
pNewNode->data = value;
pNewNode->next = pCurNode->next;
pCurNode->next = pNewNode;
return true;
}
5、削除
bool delete_index_element(pNode pHead, int i, int *value)
{
int j = 1;
pNode pCurNode = pHead;
while (!pCurNode->next || j < i)
{
pCurNode = pCurNode->next;
j++;
}
if (!pCurNode->next || i < j)
{
return false;
}
*value = pCurNode->next->data;
pNode q=pCurNode->next;//必要操作,防止下一步pCurNode->next丢失掉需要释放空间的结点
pCurNode->next = pCurNode->next->next;
free(pCurNode->next);
return true;
}
6、リンクリスト全体を作成します
リンクリストの作成は、挿入方法によって、挿入前と挿入後の2つのタイプに分けることができます。
尻尾挿入
//尾部插入法
void create_random_list(pNode* pHead, int n)
{
srand(time(0));//初始化种子
*pHead = (pNode)malloc(sizeof(Node));//创建头结点
pNode pFinalNode = *pHead;
pNode pNewNode = nullptr;
for (int i = 0; i < n; i++)
{
pNewNode = (pNode)malloc(sizeof(Node));
pNewNode->data = rand() % 100 + 1;
cout << pNewNode->data << endl;
pFinalNode->next = pNewNode;
pFinalNode = pNewNode;
}
pFinalNode->next = nullptr;
}
//头部插入法
void front_create_list(pNode* pHead, int n)
{
srand(time(0));//初始化种子
*pHead = (pNode)malloc(sizeof(Node));//创建头结点
pNode pNewNode = nullptr;
for (int i = 0; i < n; i++)
{
pNewNode = (pNode)malloc(sizeof(Node));
pNewNode->data = rand() % 100 + 1;
cout << pNewNode->data << endl;
pNewNode->next = (*pHead)->next;
(*pHead)->next = pNewNode;
}
pNewNode->next = nullptr;
}
ここでは、ヘッドポインタがポイントを変更したため、ノードにポインタを渡します。作成と削除に関与していない場合、ヘッドノードはポインタにポインタを渡すことができません。
7、リンクリスト全体を削除します
void clear_list(pNode pHead)
{
pNode pCurNode= pHead->next;
pNode pNextNode = pCurNode;
while (pCurNode)//指针域不为空
{
pNextNode = pCurNode->next;
free(pCurNode);
pCurNode = pNextNode;
}
pHead->next = nullptr;
}
[1] https://blog.csdn.net/snow_7/article/details/106919353