Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C言語で連結リストの末尾からn番目のノードを取得するプログラム

n個のノードからなる連結リストが与えられたとき、その末尾からn番目のノードを出力するのが本記事の目的です。プログラムはリスト内のノードの並び順を変更してはならず、あくまで末尾から数えてn番目に位置するノードの値を表示するだけでなければなりません。

具体例

入力 -: 10 20 30 40 50 60
  N = 3
出力 -: 40

上記の例では、先頭ノードから順に「count − n」個目までのノード(10, 20, 30, 40, 50, 60)を走査し、末尾から3番目のノードとして 40 が得られます。

効率的なアプローチ

リスト全体を最後まで走査しなくても、以下の手順で目的のノードを見つけられます。

  • ノード型の一時ポインタ(ここでは temp)を用意する
  • temp を、head ポインタが指す先頭ノードに設定する
  • カウンタをリスト内のノード総数に設定する
  • 「count − n」回だけ temp を temp→next へ進める
  • temp→data を表示する

たとえばノード数が6で n = 3 の場合、ループは「6 − 3 = 3」回繰り返されます。位置0の10から始まり、位置1の20、位置2の30、そして位置3の40に到達し、これが結果となります。この方法ならリスト全体を末尾まで辿る必要がなく、処理時間とメモリの両面で効率的です。

アルゴリズム

開始
Step 1 -> ノードの構造体を作成し、temp・next・head を構造体ノードへのポインタとして宣言する
    struct node
        int data
        struct node *next, *head, *temp
    終了
Step 2 -> リストにノードを挿入する関数を宣言する
    void insert(int val)
        struct node* newnode = (struct node*)malloc(sizeof(struct node))
        newnode->data = val
        IF head == NULL
            head = newnode に設定
            head->next = NULL に設定
        終了
        Else
            temp = head に設定
            Loop While temp->next != NULL
                temp = temp->next に設定
            終了
            newnode->next = NULL に設定
            temp->next = newnode に設定
        終了
Step 3 -> リストを表示する関数を宣言する
    void display()
        IF head == NULL
            「ノードなし」と表示
        終了
        Else
            temp = head に設定
            Loop While temp != NULL
                temp->data を表示
                temp = temp->next に設定
            終了
        終了
Step 4 -> 連結リストの末尾からn番目のノードを求める関数を宣言する
    void last(int n)
        int i を宣言
        temp = head に設定
        Loop For i = 0 and i < count - n and i++
            temp = temp->next に設定
        終了
        temp->data を表示
Step 5 -> main() 内での処理
    struct node* head = NULL としてノードを作成
    変数 n を 3 として宣言
    insert(10) を呼び出してノードを挿入
    display() を呼び出してリストを表示
    last(n) を呼び出して末尾からn番目のノードを求める
終了

C言語による実装例

#include<stdio.h>
#include<stdlib.h>
//ノードの構造体
struct node{
    int data;
    struct node *next;
}*head,*temp;
int count=0;
//リストにノードを挿入する関数
void insert(int val){
    struct node* newnode = (struct node*)malloc(sizeof(struct node));
    newnode->data = val;
    newnode->next = NULL;
    if(head == NULL){
        head = newnode;
        temp = head;
        count++;
    } else {
        temp->next=newnode;
        temp=temp->next;
        count++;
    }
}
//リストを表示する関数
void display(){
    if(head==NULL)
        printf("no node ");
    else {
        temp=head;
        while(temp!=NULL) {
            printf("%d ",temp->data);
            temp=temp->next;
        }
    }
}
//連結リストの末尾から3番目のノードを求める関数
void last(int n){
    int i;
    temp=head;
    for(i=0;i<count-n;i++){
        temp=temp->next;
    }
    printf("\n%drd node from the end of linked list is : %d" ,n,temp->data);
}
int main(){
    //リストの作成
    struct node* head = NULL;
    int n=3;
    //リストへの要素挿入
    insert(1);
    insert(2);
    insert(3);
    insert(4);
    insert(5);
    insert(6);
    //リストの表示
    printf("\nlinked list is : ");
    display();
    //末尾からn番目の要素を求める関数の呼び出し
    last(n);
    return 0;
}

実行結果

linked list is : 1 2 3 4 5 6
3rd node from the end of linked list is : 4

このように、ノード総数を管理しておけば「count − n」回のポインタ移動だけで目的のノードにアクセスできるため、シンプルかつ高速な実装が可能です。

  1. C言語で学ぶリンクリスト(連結リスト)の基本概念と4つの種類

    はじめに:配列とポインタの違いを理解しようリンクリスト(連結リスト)を理解する前に、まずC言語における「配列の欠点」と「ポインタの利点」について確認しておきましょう。この2つの違いを知ることが、リンクリストがなぜ有効なデータ構造なのかを理解する鍵となります。配列の欠点静的なメモリ割り当て:配列はコンパイル時にサイズが決定されるため、実行中にサイズを変更できません。メモリの無駄:実際に必要なデータ量より大きい配列を確保すると、未使用の領域が無駄になります。メモリ不足のリスク:逆に、確保したサイズを超えるデータは格納できず、メモリが不足する可能性があります。ポインタの利点動的なメモリ割り当て:ma

  2. 単方向リンクリストの全ノードの積を求めるアルゴリズムとC言語実装

    n個のノードで構成される単方向リンクリスト(片方向連結リスト)が与えられたとき、すべてのノードが保持する値の積を求めて出力するのがこの記事のテーマです。プログラムは先頭ノードからスタートし、リストの終端を示すNULLに到達するまで各ノードを順番にたどります。 例 入力 -: 1 2 3 4 5 出力 -: 120 上記の例では、先頭ノードから順に1、2、3、4、5のすべてのノードをたどり、それぞれの値を掛け合わせています。したがって積は 1×2×3×4×5 = 120 となります。 使用するアプローチ 以下の手順で全ノードの積を計算します。 node型の一時ポインタ(ここでは temp と