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

C言語で単方向リンクリストを使って数値を逆順に表示する方法

リンクリスト(連結リスト)とは

リンクリストは動的メモリ割り当てを利用するデータ構造で、複数の「ノード」が連なった集合体です。各ノードはデータ部分リンク部分(次のノードへのポインタ)の2つの要素で構成されています。

リンクリストの種類

C言語で扱われる主なリンクリストには、以下の4種類があります。

  • 単方向リンクリスト
  • 双方向リンクリスト
  • 循環単方向リンクリスト
  • 循環双方向リンクリスト

単方向リンクリストの構造

下の図は、単方向リンクリストの構造を示したものです。各ノードがデータと次ノードへのポインタを持ち、末尾ノードのポインタはNULLを指します。

C言語で単方向リンクリストを使って数値を逆順に表示する方法

数値を逆順に表示するCプログラム

以下は、単方向リンクリストに入力した数値を逆順に表示するCプログラムです。「ノードの作成(createNodeList)」「リストの反転(reverseDispList)」「リストの表示(displayList)」という3つの関数で構成されています。

#include <stdio.h>
#include <stdlib.h>
struct node {
    int num;
    struct node *nextptr;
}*stnode;
void createNodeList(int n);
void reverseDispList();
void displayList();
int main(){
    int n;
    printf("\n\n single Linked List : print it in reverse order :\n");
    printf("------------------------------------------------------------------------------\n");
    printf(" Input the number of nodes : ");
    scanf("%d", &n);
    createNodeList(n);
    printf("\n Data entered in the list are : \n");
    displayList();
    reverseDispList();
    printf("\n The list in reverse are : \n");
    displayList();
    return 0;
}
void createNodeList(int n){
    struct node *fnNode, *tmp;
    int num, i;
    stnode = (struct node *)malloc(sizeof(struct node));
    if(stnode == NULL) {
        printf(" Memory can not be allocated.");
    }
    else{
        // キーボードから1番目のノードのデータを読み込む
        printf(" Input data for node 1 : ");
        scanf("%d", &num);
        stnode->num = num;
        stnode->nextptr = NULL;
        tmp = stnode;
        // n個のノードを作成し、リンクリストに追加する
        for(i=2; i<=n; i++){
            fnNode = (struct node *)malloc(sizeof(struct node));
            if(fnNode == NULL) {
                printf(" Memory can not be allocated.");
                break;
            }
            else{
                printf(" Input data for node %d : ", i);
                scanf(" %d", &num);
                fnNode->num = num;
                fnNode->nextptr = NULL;
                tmp->nextptr = fnNode;
                tmp = tmp->nextptr;
            }
        }
    }
}
void reverseDispList(){
    struct node *prevNode, *curNode;
    if(stnode != NULL){
        prevNode = stnode;
        curNode = stnode->nextptr;
        stnode = stnode->nextptr;
        prevNode->nextptr = NULL; // 先頭ノードを末尾ノードとして扱う
        while(stnode != NULL){
            stnode = stnode->nextptr;
            curNode->nextptr = prevNode;
            prevNode = curNode;
            curNode = stnode;
        }
        stnode = prevNode; // 末尾ノードを先頭(ヘッド)として扱う
    }
}
void displayList(){
    struct node *tmp;
    if(stnode == NULL){
        printf(" No data found in the list.");
    }
    else{
        tmp = stnode;
        while(tmp != NULL){
            printf(" Data = %d\n", tmp->num);
            tmp = tmp->nextptr;
        }
    }
}

実行結果

上記のプログラムをコンパイルして実行すると、次のような出力が得られます。入力した順序とは逆の順序でデータが表示されていることが確認できます。

single Linked List : print it in reverse order :
------------------------------------------------------------------------------
Input the number of nodes : 5
Input data for node 1 : 12
Input data for node 2 : 45
Input data for node 3 : 11
Input data for node 4 : 9
Input data for node 5 : 10

Data entered in the list are :
Data = 12
Data = 45
Data = 11
Data = 9
Data = 10

The list in reverse are :
Data = 10
Data = 9
Data = 11
Data = 45
Data = 12

リスト反転の仕組み(ポイント解説)

reverseDispList関数では、stnodecurNodeprevNodeの3つのポインタを使いながらリストを先頭から走査し、各ノードのnextptrを「前のノード」へ向き直すことで反転を実現しています。

具体的には、まず先頭ノードのnextptrをNULLに設定して末尾ノードに変え、その後ループ処理で各ノードのリンクを逆向きにつなぎ替えます。ループが完了した時点で、元の末尾ノードを新しい先頭(ヘッド)としてstnodeに代入すれば、反転されたリストの完成です。この手法なら余分なメモリを消費せず、O(n)の計算量でリスト全体を反転できます。

  1. 【C言語】forループを使って1〜Nまでの素数をすべて表示するプログラム

    問題 実行時にユーザーが入力した値nに対して、1からnの間に存在するすべての素数を表示するC言語プログラムを作成しましょう。 解決策 ここでは、forループを使用して、実行時にユーザーから与えられた値nまでの範囲内にある素数をすべて検出・表示する方法を解説します。なお、素数とは、1とその数自身以外に約数を持たない、1より大きい自然数のことです。具体的には、2、3、5、7、11、13などが該当します。 アルゴリズム 以下は、実行時にユーザーが入力した値nまでの素数をすべて表示するためのアルゴリズムです。 ステップ1 − nの値を入力として読み込む ステップ2 − カウンタ変数countを0で初

  2. C言語で連結リストを使った優先度付きキューの実装方法

    本記事では、整数値の「データ」と「優先度」が与えられたとき、指定された優先度に従って連結リスト(リンクリスト)を構築し、結果を表示する方法を解説します。 優先度付きキューとは キューはFIFO(First In, First Out:先入れ先出し)方式のデータ構造であり、最初に挿入された要素が最初に取り除かれます。 一方、優先度付きキュー(プライオリティキュー)は、要素の挿入・削除を「優先度」に基づいて行えるキューの一種です。キュー、スタック、連結リストなどのデータ構造を用いて実装でき、以下のルールに従って動作します。 優先度が最も高いデータ(要素)は、優先度が低いものよりも先に処理される。