单列表插入列表末尾

rez*_*vor 1 c++ singly-linked-list

我试图在不使用ListIterator的情况下,定义并实现一个名为insert_back的新操作,该操作接受单个模板Object并在列表末尾插入Object.在不改变此操作或任何其他操作的含义的情况下,我需要修改List的表示并更改使insert_back在常量时间运行所需的任何方法:O(1).

我真的很难实现这一点.

我想创建另一个名为INSERTBACK的菜单选项,它将在列表的末尾插入一个新对象

LIST.H

 #ifndef LIST_H
#define LIST_H
#include <iostream>
#include "ListNode.h"
#include "ListIterator.h"

namespace cs20 {

template <class Object>
class List {
    public:
    List();
    List( const List& rhs );
    ~List();

    bool isEmpty() const;
    bool isIncreasing() const;
    void makeEmpty();
    ListIterator<Object> zeroth() const;
    ListIterator<Object> first() const;
    void insert( const Object& data,
                 const ListIterator<Object> &iter );
    void insert( const Object& data );
    void insert_back( const Object& data );
    ListIterator<Object> findPrevious( const Object& data ) const;
    void remove( const Object& data );

    const List& operator =( const List& rhs );
    const List& operator <<( const List& rhs );
private:
    ListNode<Object> * head;
    ListNode<Object> * tail;

};

}
#endif
Run Code Online (Sandbox Code Playgroud)

LIST.CPP

 #ifndef LIST_CPP
#define LIST_CPP

#include "List.h"

namespace cs20 {
template <class Object>
List<Object>::List() {
    head = new ListNode<Object>;
    tail->nextIsNull();
}

template <class Object>
List<Object>::List( const List<Object>& rhs ) {
    head = new ListNode<Object>;
    tail->nextIsNull();
    *this = rhs;
}

template <class Object>
List<Object>::~List() {
    makeEmpty();
    delete head;
}

template <class Object>
bool List<Object>::isEmpty() const {
    return( head->nextIsNull() );
}

template <class Object>
void List<Object>::makeEmpty() {
    while (!isEmpty()) {
        remove( first().retrieve() );
    }
    tail = NULL;
}

template <class Object>
ListIterator<Object> List<Object>::zeroth() const {
    return( ListIterator<Object>( head ) );
}

template <class Object>
ListIterator<Object> List<Object>::first() const {
    return( ListIterator<Object>( head->getNext() ) );
}

template <class Object>
void List<Object>::insert( const Object& data,
                           const ListIterator<Object> &iter ) {
    if (iter.isValid()) {
        ListNode<Object>* newnode = new ListNode<Object>( data, iter.current->getNext() );
        iter.current->setNext( newnode );
    }
}

template <class Object>
void List<Object>::insert( const Object& data ) {

    ListNode<Object>* newnode = new ListNode<Object>( data, head->getNext() );
    head->setNext( newnode );
}


template <class Object>
void List<Object>::insert_back( const Object& data ) {
    ListNode<Object>* newnode = new ListNode<Object>( data, tail->getNext() );
    if( tail != NULL )
    {
        tail->setNext( newnode );
    }
    tail = newnode;
    if( head->getNext() == NULL )     {
        head->setNext(newnode);
    }
}


template <class Object>
ListIterator<Object> List<Object>::findPrevious( const Object& data ) const {
    ListNode<Object>* node = head;
    while( node->getNext() != NULL && node->getNext()->getElement() != data ) {
        node = node->getNext();
    }
    if (node->getNext() == NULL) {
        node = NULL;
    }
    return ListIterator<Object>( node );
}


template <class Object>
bool List<Object>::isIncreasing() const {
        ListNode<Object>* node= head;
        while (node->getNext() != NULL)
        {
            if (node->getNext()->getElement() <= node->getElement())
                return false;
            node = node->getNext();
        }
        return true;
    }


template <class Object>
void List<Object>::remove( const Object& data ) {
    ListIterator<Object> iter = findPrevious( data );
    if (iter.isValid()) {
        ListNode<Object>* node = findPrevious( data ).current;
        if (node->getNext() != NULL) {
            ListNode<Object> *oldNode = node->getNext();
            node->setNext( node->getNext()->getNext() );  // Skip oldNode
            delete oldNode;
        }
    }
}

// Deep copy of linked list
template <class Object>
const List<Object>& List<Object>::operator =( const List<Object>& rhs ) {
    if (this != &rhs) {
        makeEmpty();

        ListIterator<Object> rightiter = rhs.first( );
        ListIterator<Object> myiterator = zeroth();
        while( rightiter.isValid() ) {
            insert( rightiter.retrieve(), myiterator );
            rightiter.advance();
            myiterator.advance();
        }
    }
    return( *this );
}

}

#endif
Run Code Online (Sandbox Code Playgroud)

实施LISTMENU.CPP

// Menu.cpp:定义控制台应用程序的入口点.//

#include <iostream>
#include "List.h"
#include "ListNode.h"
#include "ListIterator.h"
#include "List.cpp"
#include "ListNode.cpp"
#include "ListIterator.cpp"

using namespace std;
using namespace cs20;

enum CHOICE {MAKEEMPTY, REMOVE, ISEMPTY, FINDPREVIOUS, INSERT, QUIT, PRINT };

CHOICE menu();
void printList( const List<int>& l );

int main(int argc, char* argv[]) {
    int value;
    List<int> list;
    ListIterator<int> iter;

    CHOICE choice;
    do {
        choice = menu();
        switch( choice ) {
        case MAKEEMPTY:
            list.makeEmpty();
            break;
        case ISEMPTY:
            if (list.isEmpty()) {
                cout << "list is empty" << endl;
            }
            else {
                cout << "list is not empty" << endl;
            }
            break;
        case REMOVE:
            cout << "Please provide int to remove: ";
            cin  >> value; 
            list.remove( value );
            break;
        case INSERT:
            cout << "Please provide int to insert: ";
            cin  >> value; 
            list.insert( value );
            break;
        case FINDPREVIOUS:
            cout << "Please provide int to find: ";
            cin  >> value; 
            iter = list.findPrevious( value );
            if (iter.isValid()) {
                cout << "previous element = " << iter.retrieve() << endl;
            }
            else {
                cout << "data element was not found!" << endl;
            }
            break;
        case PRINT:
            printList( list );
            break;
        case QUIT:
            break;
    }   

    } while (choice != QUIT);

    return( 0 );
}

int sample() {
    cout << "Forming Lists" << endl;
    int one = 1, two = 2;
    List<int> l1 = List<int>();
    List<int> l2 = List<int>();

    l1.insert( one );
    l1.insert( two );

    cout << "print l1" << endl;
    printList( l1 );

    cout << "l2 = l1" << endl;
    l2 = l1;

    cout << "print l2" << endl;
    printList( l2 );    

    cout << "l1.remove(one)" << endl;
    l1.remove( one );

    cout << "print l1" << endl;
    printList( l1 );

    cout << "print l2" << endl;
    printList( l2 );
    cout << "findPrevious 1 in l2" << endl;
    ListIterator<int> iter = l2.findPrevious( one );
    if (iter.isValid()) {
        cout << "--iter valid" << endl;
        cout << iter.retrieve() << endl;
    }
    else {
        cout << "--iter not valid" << endl;
    }

    cout << "findPrevious 2 in l2" << endl;
    iter = l2.findPrevious( two );
    if (iter.isValid()) {
        cout << "--iter valid" << endl;
        cout << iter.retrieve() << endl;
    }
    else {
        cout << "--iter not valid" << endl;
    }

    cout << "findPrevious 1 in l1" << endl;
    iter = l1.findPrevious( one );
    if (iter.isValid()) {
        cout << "--iter valid" << endl;
        cout << iter.retrieve() << endl;
    }
    else {
        cout << "--iter not valid" << endl;
    }

    cout << "findPrevious 2 in l1" << endl;
    iter = l1.findPrevious( two );
    if (iter.isValid()) {
        cout << "--iter valid" << endl;
        cout << iter.retrieve() << endl;
    }
    else {
        cout << "--iter not valid" << endl;
    }

    cout << "print l1" << endl;
    printList( l1 );    

        // you can remove whatever you want, whether it exists or not
    cout << "l1.remove(one)" << endl;
    l1.remove( one );

    cout << "print l1" << endl;
    printList( l1 );    

    return( 0 );
}

void printList( const List<int>& l ) {
    if (l.isEmpty())
        cout << "Empty list" << endl;
    else {
        ListIterator<int> iter = l.first();
        while (iter.isValid()) {
            cout << iter.retrieve() << " -> ";
            iter.advance();
        }
        cout << "NULL";
        cout << endl;
    }
}

CHOICE menu() {
    char choice;
    CHOICE result;
    cout << "(M)akeEmpty I(s)Empty (R)emove (I)nsert (F)indPrevious (P)rint (Q)uit: " << endl;
    cin  >> choice;
    switch( choice ) {
    case 'M':
    case 'm':
        result = MAKEEMPTY;
        break;
    case 'S':
    case 's':
        result = ISEMPTY;
        break;
    case 'R':
    case 'r':
        result = REMOVE;
        break;
    case 'I':
    case 'i':
        result = INSERT;
        break;
    case 'F':
    case 'f':
        result = FINDPREVIOUS;
        break;
    case 'Q':
    case 'q':
        result = QUIT;
        break;
    case 'P':
    case 'p':
        result = PRINT;
        break;
    }

    return( result );
}
Run Code Online (Sandbox Code Playgroud)

编辑:添加ListNode.cpp ListNode.CPP

 #ifndef LISTNODE_CPP
#define LISTNODE_CPP

#include "ListNode.h"

namespace cs20 {

template <class Object>
ListNode<Object>::ListNode( const Object& theElement,
                                    ListNode<Object> * node ) {
    element = theElement;
    next = node;
}

template <class Object>
bool ListNode<Object>::nextIsNull() const {
    return( next == NULL );
}

template <class Object>
const Object& ListNode<Object>::getElement() const {
    return( element );
}

template <class Object>
ListNode<Object>* ListNode<Object>::getNext() const {
    return( next );
}

template <class Object>
void ListNode<Object>::setNext( ListNode<Object> * node ) {
    next = node;
}

}

#endif
Run Code Online (Sandbox Code Playgroud)

Chu*_*ill 5

您当前定义的链接列表称为单链接列表,因为您有一个指针(下一个),并且您只存储指向列表头部的指针.将名为tail的附加指针添加到List容器中,并将其指向最后一个元素.您需要调整List方法以正确分配尾部并对其进行寻址.

另一种方法可能是将列表转换为带有(next,previous)指针的双链表,然后你可以保持head-> previous指向列表的尾部(双链循环列表).

第三种方法是使单链表循环,但将指针存储为上一个和下一个指针的XOR(参见:http://en.wikipedia.org/wiki/XOR_linked_list).


下面是一些示例,您需要进行一些更改,以便将"尾部"成员添加到List中,并使用它来创建insert_back操作.

列表实现似乎甚至将新节点添加到空列表中.

将成员添加到List.h定义中,

void insert_back( const Object& data );
ListNode<Object>* head;
ListNode<Object>* tail;  //add a tail
Run Code Online (Sandbox Code Playgroud)

您的列表实现甚至在空列表上创建ListNode.不确定你打算这样做.不管怎样,在你的构造,初始化尾(通常是空的,也许你要初始化你在列表中放置浪费节点).

List<Object>::List() {
    head = new ListNode<Object>;
    tail = NULL; //or = head
}
Run Code Online (Sandbox Code Playgroud)

你也有名单分配,这是除了你与你指定给(你不叫makeEmpty)列表中的节点(或多个)做很好,但你需要在这里做一些理智与尾 - 但因为你只是分配,我将设置尾= NULL,提醒你做一些理智,

List<Object>::List( const List<Object>& rhs ) {
    head = new ListNode<Object>;
    tail = NULL; //or = head
    *this = rhs; //the list node you just assigned is lost here
}
Run Code Online (Sandbox Code Playgroud)

当你做空时,你的尾巴需要被清空,

void List<Object>::makeEmpty() {
    while (!isEmpty()) {
        remove( first().retrieve() );
    }
    tail = NULL;
}
Run Code Online (Sandbox Code Playgroud)

当列表为空时,您现有的插入方法需要初始化尾部,作为练习,

你将需要一个insert_back方法,该方法仅需要指向tail->下在新的节点(如果有一个尾),然后设置尾到新节点,

template <class Object>
void List<Object>::insert_back( const Object& data ) {
    // insert after the tail node
    ListNode<Object>* newnode = new ListNode<Object>( data, tail->getNext() );
    if( tail != NULL ) //not empty, point tail->next at newnode
    {
        tail->setNext( newnode );
    }
    tail = newnode;
    if( head->getNext() == NULL ) //empty, newnode is head and tail
    {
        head->setNext(newnode);
    }
}
Run Code Online (Sandbox Code Playgroud)