0

C ++のリンクリストを理解するには、深刻な助けが必要です。数週間前に配列構造を使用して作成したプログラムを使用して、それらをリンクリストに変換し、いくつかの新しい関数を追加すると思います。私の大きな懸念は、リンクリストに自信がなく、ここや他のサイトでそれらの知識を得るために時間を費やしていることです。しかし、私が今直面している問題に関連するのに役立つ情報源を見つけることができません。

これが私の元のコードです:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX 100

struct YouTubeVideo { 
char video_name[1024];        // YouTube video name
int video_ranking;            // Number of viewer hits
char video_url[1024];         // YouTube URL
};

struct YouTubeVideo Collection[MAX];

int tail = 0;

//-- Forward Declaration --// 
void printall();
void insertion();
void sort();
void branching(char option);        
void menu(); 
void load_file();
void save_file();

int main()
{
char ch; 

load_file();

printf("\n\nWelcome to CSE240: YouTube Classic Hits\n");

do {
     menu();
     fflush(stdin);                 // Flush the standard input buffer 
     ch = tolower(getchar());       // read a char, convert to lower case
     branching(ch);
} while (ch != 'q');

return 0; 
}

void menu()
{
 printf("\nMenu Options\n");
 printf("------------------------------------------------------\n");
 printf("i: Insert a new favorite\n");
 printf("p: Review your list\n"); 
 printf("q: Save and quit\n");
 printf("\n\nPlease enter a choice (i, p, or q) ---> "); 
}

void branching(char option)
{
switch(option)
{
    case 'i':
        insertion();
        sort();
    break;

    case 'p':
        printall();
    break;

    case 'q':
        save_file();
    break;

    default:
        printf("\nError: Invalid Input.  Please try again..."); 
    break;
}
}

void insertion()
{
if(tail < MAX)
{
    printf("\nWhat is the name of the video? (No spaces characters allowed)\n");
    scanf("%s", Collection[tail].video_name);

    printf("\nHow many viewer hits does this video have?\n");
    scanf("%d", &Collection[tail].video_ranking);

    printf("\nPlease enter the URL: ");
    scanf("%s", Collection[tail].video_url);

    tail++;
}
else
{
    printf("\nERROR: Your collection is full. Cannot add new entries.\n");
}
}

void sort()
{
int i = 0, j = 0; 
struct YouTubeVideo temp;

for(i = 0; i < tail; i++)
{
    for(j = i+1; j < tail; j++)
    {
        if(Collection[i].video_ranking < Collection[j].video_ranking)
        {
            temp = Collection[i];
            Collection[i] = Collection[j];
            Collection[j] = temp;
        }
    }
}

//RA: I think it's easier (and faster) to assume your current list is already
//    sorted and then insert your new element into the correct position. (You
//    can show this maintains a sorted list by induction.)

printf("\nSorting Complete...\n");
}

void printall()
{
int i; 

printf("\nCollections: \n"); 

for(i = 0; i < tail; i++)
{
    printf("\nVideo Name: %s", Collection[i].video_name);
    printf("\nRanking (Hits): %d", Collection[i].video_ranking);
    printf("\nURL: %s", Collection[i].video_url);
    printf("\n");
}
}

void save_file() { 
FILE *fileName;                                     // declare a pointer to File type 
char ch; 
int index = 0; 

fileName = fopen("ranking.dbm", "wb");              // "b" for binary mode 
                                                        // ìwî for write


if(fileName != NULL) 
{   
    fwrite(&tail, sizeof(int), 1, fileName);        // Write tail to the     file for later retrieval.

    for(index = 0; index < tail; index++)
    { 
        fwrite(&Collection[index].video_name, 1024, 1, fileName); 
        fwrite(&Collection[index].video_ranking, sizeof(int), 1, fileName);     
        fwrite(&Collection[index].video_url, 1024, 1, fileName);
    } 

    fclose(fileName);
} 
else 
    printf ("ERROR: Could not open file for saving data !\n"); 
}

void load_file() { 
FILE *fileName;                         // declare a pointer     to File type 
int index = 0; 

fileName = fopen("ranking.dbm", "rb");  // "b" for binary mode 
                                    // ìrî           for read

if(fileName != NULL) {   
    fread(&tail, sizeof(int), 1, fileName);

    for(index = 0; index < tail; index++) 
    {
        fread(Collection[index].video_name, 1024, 1, fileName);
        fread(&Collection[index].video_ranking, sizeof(int), 1, fileName);
        fread(Collection[index].video_url, 1024, 1, fileName);
    }

    fclose(fileName);
}
else 
    printf ("ERROR: Could not open file for loading data !\n"); 
}

これらは私がすることになっていることのための正確な指示です:

Convert the “YouTubeVideo” array structure (Collection) into a linked-list. The program must sort (by “video_name”) the entries as they are inserted into the linked-list. [30 points] (*Note: You will lose 10 points if the linked list is not sorted.)

今、私は現在の理解でできると信じている限りそれをうまくやっていますが、私は今問題に直面しています。

これが私の解決策を試みたコードです:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

using namespace std;

#define MAX 100

 struct YouTubeVideo
{
char name[1024];        // YouTube video name
int ranking;                // Number of viewer hits
char url[1024];             // YouTube URL
};

struct YouTubeVideo Collection[MAX];

int tail = 0;

//-- Forward Declaration --//
void printall();
void insertion();
void branching(char option);
void menu();


int main()
{
char ch;

// TODO: Add code to load save data from file

cout << "\n\nWelcome to CSE240: YouTube Classic Hits\n";

do {
    menu();
    cin >> ch; // read a char, convert to lower case
    cin.ignore();

    ch = tolower(ch);
    branching(ch);
} while (ch != 'q');

return 0;
}

void menu()
{
cout << "\nMenu Options\n";
cout << "------------------------------------------------------\n";
cout << "i: Insert a new favorite\n";
cout << "p: Review your list\n";
cout << "s: Search\n";
cout << "d: Delete an entry\n";
cout << "q: Save and quit\n";
cout << "\n\nPlease enter a choice (i, p, s, d, or q) ---> ";
}

void branching(char option)
{
switch(option)
{
    case 'i':
        insertion();
        break;

    case 'p':
        printall();
        break;

    case 's':
        // TODO: Add code to search for a particular node by name
        break;

    case 'd':
        // TODO: Add code to remove a node
        break;

    case 'q':
        // TODO: Add code to save data into a file
        break;

    default:
        cout << "\nError: Invalid Input.  Please try again...";
        break;
}
}

void insertion() { // insert a new entry
struct YouTubeVideo *p, *temp;
p = (struct YouTubeVideo *) malloc(sizeof(struct YouTubeVideo)); if (p == 0) {
    printf("out of memory\n"); return; }
printf("Enter Video name, Views, URL: \n"); scanf("%s", p->name); // p->name is array         scanf("%d", &p->phone);
scanf("%s", p->ranking);
temp = head;
if ((head == NULL)||(strcmp(p->name, temp->name) <=0)) {
    p->next = head;
    head = p;
}

else {
    while (temp->next != NULL) {
        if (stricmp(p->name, temp->next->name) <=0) { p->next = temp->next;
            temp->next = p;
            return;
        } else
            temp = temp->next; }
    p->next = NULL;
    temp->next = p;
} }

void printall()
{
int i;

cout << "\nCollections: \n";

for(i = 0; i < tail; i++)
{
    cout << "\nVideo Name: " << Collection[i].name << "\n";
    cout << "\nRanking (Hits): " << Collection[i].ranking << "\n";
    cout << "\nURL: " << Collection[i].url << "\n";
    cout << "\n";
}
}

私が抱えている問題は、insertionエラーが発生undeclared identifier headしていることですno member named next in YouTubeVideo。たくさんの場所に配置して宣言しようとしましたが、これらのエラーを修正できないようです。

私はあなたが私に与えることができるいくつかの助けと可能な知識を本当に感謝します。私は本当にこれを大いにやりましたが、今は立ち往生しています。

4

3 に答える 3

1

さて、私はあなたにリンクリストがC ++で何であるかについての簡単な概要をあなたに与えるために最善を尽くしますが、それでもあなたはあなた自身であなたの割り当てをすることによってあなたに学ぶことができます。あなたのコードはほとんどCでした、これはもっとC ++スタイルになりますが、私はテンプレートを避け、C++の獣医が物事をより簡潔にするかもしれないところに物事を綴ることがあります。

整数を保持する単一リンクリストの典型的な単純なノード構造体は次のとおりです。

struct LinkedListNode
{
  int value;
  LinkedListNode* next;
};

このノードは1つの整数を保持し、さらにリスト内の次のノードへのポインターを保持します。

このようなリンクリストのインターフェイスは次のようになります。

struct LinkedList
{
public:
  LinkedList();
  bool isEmpty() const;
  int valueAtBeginning() const;
  void insertAtBeginning(int newValue);

private:
  LinkedListNode* head;
};

このクラスは、コンストラクター(リンクリストを作成する方法)、リストに新しいアイテムを挿入する方法、リストの最初の値を取得する方法、およびリストが空かどうかを確認する方法を提供します。また、(独自の参照のために)リストの最初のノードへのポインターを保持します。

これらを実装する方法を実行してみましょう。

コンストラクターは次のとおりです。

LinkedList::LinkedList():
  head(NULL)
{
}

この関数は、「最初のアイテム」ポインタをNULLに初期化します。これは、「リストが空であるため、最初の項目がない」ためのコードになります。そういえば:

bool LinkedList::isEmpty() const
{
  return (head == NULL);
}

この関数は、「ヘッドポインタがnullの場合、リストは空です。それ以外の場合は空ではありません」と言います。メソッドがどのようにマークされているかに注意してくださいconst。これにより、このコードがリストのどの部分も変更しないことが約束されます。

次も簡単です。

int LinkedList::valueAtBeginning() const
{
  assert(!isEmpty());
  return head->value;
}

この関数は、リストの最初の項目へのポインターをたどり、そのvalueメンバーを取り出して返します。また、リストが空ではないと主張します。これにより、空のリストから何かを要求するのを間違えたかどうかを簡単に見つけることができます。const繰り返しになりますが、リストは変更されないため、メソッドがどのようにマークされているかに注意してください。

最後に、最初に新しいものを追加します。

void LinkedList::insertAtBeginning(int newValue)
{
  LinkedListNode* oldHead = head;
  LinkedListNode* newHead = new LinkedListNode();
  newHead->value = newValue;
  newHead->next = oldHead;
  head = newHead;
}

これは概念的には十分に単純です。新しいノードを作成し、リストの先頭に貼り付けます。古い最初のアイテムが2番目のアイテムになります。newまた、ここでCの代わりにC++を使用していることに注意してmallocください。クイズ:リストが空の場合、これは機能しますか?

さて、整数以上のものを格納するのはあなたに任せます。また、リストから最初の項目を削除するメソッドを作成する方法を理解してください(CではdeleteなくC ++を使用free)。次に、リストを「トラバース」するメソッドを作成して、各整数を出力します。それを理解したら、最後または途中で追加/削除するメソッドを書いてみてください。

于 2012-10-11T21:46:18.580 に答える
1

実際にリンクリストを実装する必要があります。これは宿題のように見えるので、C++のどこまで進んでいるのか疑問に思います。クラスやオブジェクト指向プログラミングをまだ実際に行っていない場合、これを修正する最も簡単な方法は、YouTubeビデオ構造体に次のオブジェクトと前のオブジェクトを追加することです。このような:

struct YouTubeVideo {   
    char video_name[1024];        // YouTube video name  
    int video_ranking;            // Number of viewer hits 
    char video_url[1024];         // YouTube URL  
    YouTubeVideo* next;
    YouTubeVideo* previous;
};  

次に、head宣言を追加する必要があります。これはタイプYouTubeVideo*になります。最初のビデオを追加するときは、このビデオを指すように頭を設定します。その後、新しいビデオを追加するときはいつでも、ヘッドビデオの次のポインターが新しいビデオを指すように設定し、新しいビデオの前のポインターがヘッドビデオを指すようにします。これがリンクリストの始まりですが、ソリューションはまだ非常に厄介です。

私があなたなら、いくつかのリンクリストクラスがどのように実装されているかを見ていきます。これが私が書いた最初のリンクリストクラスのヘッダーファイルです:

#ifndef LINKEDLIST_H 
#define LINKEDLIST_H

#include "List.h" 

class LinkedList : public List { 
 public: 
  LinkedList();
  virtual double get(int index) const; 
  virtual void add(double item); 
  virtual void insert(int index, double item); 
  virtual double delete_item(int index); 
  virtual int size() const;  
 private:
  class Node;
  Node* first;
  Node* last;
  int listsize;
}; 
class LinkedList::Node{
 public:
  double value;
  Node* next;
};

#endif

このリストにはクラスNodeが含まれており、このクラスには値が含まれていることがわかりますdouble value。このコードを使用する場合は、ノードクラスにYouTubeVideo*値のフィールドを含める必要があります。

于 2012-10-11T21:46:26.783 に答える
0

簡単に言うと、(構造体型の)配列を同じフィールドを持つリンクリストに変換する必要があります。

#include <stdio.h>
#include <stdlib.h>

struct LL
{
    char name[1024];        // YouTube video name
    int ranking;                // Number of viewer hits
    char url[1024];             // YouTube URL

    struct LL *next; // pointer to the next element
};

// this is from your code
#define MAX 100
struct YouTubeVideo
{
    char name[1024];        // YouTube video name
    int ranking;                // Number of viewer hits
    char url[1024];             // YouTube URL
};

// now you have an array of those structs
struct YouTubeVideo Collection[MAX];

// and you can fill it up as you wish

int main(int argc, char**argv)
{
    struct LL *ll = NULL;

    for (int i = 0; i < MaxElements; i++)
    {
        // we have a blob of memo to store your stuff
        x=(struct LL*)calloc(1, sizeof(struct LL));
        if (x != NULL)
    {
        // just run out of memory
        // so handle the error
    }
        else
    {
        // nothing to do just copy fields of Collection[i]
        // to the newly allocated space
        x->name    = strdup(Collection[i].name);
        x->ranking = Collectionp[i].ranking;
        x->url     = strdup(Collection[i].name);
        x->next    = NULL;

        // since you want your result sorted we need to find its
        // location in the linked list

        if (ll == NULL) // if the list is empty
        {
            ll=x;
            // and nothing else to do since a list with a single element
            // is always sorted
        }
        else
        {
            struct LL *p = ll, *q = ll;
            // need to find where in the list should x be inserted
            // p is not null (see the assignment above) so we
            // always can call strcmp on it. also for x

            while (p!=NULL && strcmp(p->name, x->name) < 0)
        // p can become null if your struct is to become the last
        // in the linked list: the order of comparisons are
        // important
        {
            q=p; // we need q, the parent node because it is
                 // the parent node's next pointer needs to be modified
            p=p->next;
        }
            // once we get here p points to an LL structure or NULL if
            // the element to be inserted will be the last in the list
            // q points to the element before p

                // one more trick: if element being inserted is comes earlier than
                // the first element we need to modify ll
                if (q == ll)
                {
                 x->next = ll;
                 ll = x;
                }
                else
                {
                    x->next=q->next;
                    q->next=x;

                // these lines don't fiddle with p
            }
     }
  }

}

おそらく、コードを関数に入れたいと思うでしょう。単一のリンクリストに挿入することは、二重のリンクリストに挿入するよりも少し注意が必要ですが、ポインタを節約できることに注意してください。そして警告の言葉:私はこれをテストしていません、ただそれの論理をタイプしました。

于 2012-10-11T22:38:06.177 に答える