Linked list void Insert(element x, cell * p);

0

Cześć, napisałem kod na linked list tylko że np. w funkcji Insert zamiast void Insert(element x, cell * p); zaimplementowałem void Insert(element x, int position); z czego się dowiedziałem że jest to niepoprawne, próbuję teraz całość przerobić tak żeby poprawnie działało ale nie mogę zrozumieć jak to zaimplementować.

Mój obecny kod:

/*

Metody klasy reprezentującej listę jednokierunkową*:

        void Insert(element x, cell * p); // wstawia element x na pozycję next komórki o wskaźniku p
                                          // (lub w przypadku pustej listy tworzy komórkę z elementem x w miejscu głowy listy)
        void Delete(cell * p); // usuwa komórkę z pozycji next komórki o wskaźniku p
        cell * Locate(element x); // zwraca wskaźnik do pierwszej komórki z elementem x
        cell * First(); // zwraca wskaźnik do pierwszej komórki na liście
        cell * Next(cell * p); // zwraca wskaźnik do kolejnej komórki po komórce o wskaźniku p
        cell * Previous(cell * p); // zwraca wskaźnik do komórki poprzedzającej komórkę o wskaźniku p
        cell * Last(); // zwraca wskaźnik do ostatniej komórki na liście
        void print(); // wyświetla wszystkie elementy listy

*/

#include <iostream>

using namespace std;

template <typename T>
struct Node
{
    T data;
    Node *next;
};

template <typename T>
class LinkedList
{
public:
    Node <T> *head;

    LinkedList()
    {
        head = NULL;
    }

    T First()// zwraca wskaźnik do pierwszej komórki na liście
    {
        Node <T> *temp = head;
        return 1;
    }

    T Last()// zwraca wskaźnik do ostatniej komórki na liście
    {
        Node <T> *temp = head;
        int counter = 0;
        while (temp != NULL)
        {
            temp = temp->next;
            counter++;
        }
        return counter + 1;
    }

    T Next(int position)//zwraca wskaźnik do kolejnej komórki po komórce o wskaźniku p
    {
        if (position < 1 || position > Last())
        {
            cout << "\nposition should be >= 1 or <= " << Last() - 1;
            return -1;
        }
        else
        {
            return position + 1;
        }
    }

    T Previous(int position)//zwraca wskaźnik do poprzedniej komórki po komórce o wskaźniku p
    {
        if (position < 1 || position > Last())
        {
            cout << "\nposition should be >= 2 or <= " << Last();
            return -1;
        }
        else
        {
            return position - 1;
        }
    }

    void Insert(T newElement, int position)// wstawia element x na pozycję next komórki o wskaźniku p
                                          // (lub w przypadku pustej listy tworzy komórkę z elementem x w miejscu głowy listy)
    {
        Node<T> *newNode = new Node<T>();
        newNode->data = newElement;
        newNode->next = NULL;

        if (position < 1)
        {
            cout << "\nposition should be >= 1.";
        }
        else if (position == 1)
        {
            newNode->next = head;
            head = newNode;
        }
        else
        {

            Node <T>*temp = head;
            for (int i = 1; i < position - 1; i++)
            {
                if (temp != NULL)
                {
                    temp = temp->next;
                }
            }

            if (temp != NULL)
            {
                newNode->next = temp->next;
                temp->next = newNode;
            }
            else
            {
                cout << "\nThe previous node is null.";
            }
        }
    }

    T Locate(T searchValue)
    {
        Node <T> *temp = head;
        int found = 0;
        int i = 0;

        if (temp != NULL)
        {
            while (temp != NULL)
            {
                i++;
                if (temp->data == searchValue)
                {
                    found++;
                    break;
                }
                temp = temp->next;
            }
            if (found == 1)
            {
                return i;
            }
            else
            {
                cout << searchValue << " is not found in the list.\n";
                return Last();
            }
        }
        else
        {
            cout << "The list is empty.\n";
            return Last();
        }
    }

    void Delete(int position)
    {
        Node<T> *temp1 = head;
        Node<T> *temp2 = NULL;
        int ListLen = 0;

        if (head == NULL)
        {
            cout << "List is empty." << endl;
            return;
        }

        while (temp1 != NULL)
        {
            temp1 = temp1->next;
            ListLen++;
        }

        if (ListLen < position)
        {
            cout << "Index is out of range od linked list" << endl;
            return;
        }

        temp1 = head;

        if (position == 1)
        {

            head = head->next;
            delete temp1;
            return;
        }

        while (position-- > 1)
        {
            temp2 = temp1;
            temp1 = temp1->next;
        }

        temp2->next = temp1->next;
        delete temp1;
    }

    void print()
    {
        Node<T> *temp = head;
        if (temp != NULL)
        {
            cout << "The list contains: ";
            while (temp != NULL)
            {
                cout << temp->data << " ";
                temp = temp->next;
            }
            cout << endl;
        }
        else
        {
            cout << "The list is empty.\n";
        }
    }
};

int main()
{
    LinkedList <int> MyList;

    MyList.Insert(2312, 1);
    MyList.print();

    MyList.Insert(32, 1);
    MyList.print();

    MyList.Insert(3423, 3);
    MyList.print();

    MyList.Insert(888, MyList.First());
    MyList.print();

    MyList.Insert(222, MyList.Last());
    MyList.print();

    MyList.Insert(69, 4);

    MyList.Insert(420, MyList.Last());
    MyList.print();

    MyList.Insert(20, MyList.Next(3));
    MyList.print();

    MyList.Delete(MyList.Locate(32));
    MyList.print();
}

I tak jak w komentarzu na samym początku funkcje Insert, Delete, Next i Previous mają przyjąć wskaźnik do komórki. Wyjaśni ktoś jak to zaimplementować ?

2

Tu masz od groma problemów:
Konstruktor: LinkedList():head(nullptr) {}
jak ja widzę takie rzeczy:

  T First()// zwraca wskaźnik do pierwszej komórki na liście
    {
        Node <T> *temp = head;
        return 1; // to co zwraca wskaźnik czy 1?
    }

To mi się odechciewa dalej czytać.
W liście z dowiązaniami nie ma komórek, jest węzeł a w nim dane, czy na pewno chcesz zwrócić dane? A co jeżeli lista jest pusta?
Na jednokierunkowej liście nie powinieneś implementować czegoś takiego jak: Last() jeżeli obok *head nie masz *tail.
Żadna z metod nie powinna smarować po konsoli, smarowanie po konsoli zostaw dla metody/klasy kontrolującej.
Zacznij na reszcie pisać we współczesnym C++.

W kodzie poniżej masz zrealizowane wszystko oprócz next() i prev() (sam sobie dodasz), zauważ o ile mniej kodu jak podejść do tego sensownie.

#include <algorithm>
#include <iostream>
#include <memory>
using namespace std;
 
template<typename T> class List
{
	public:
	class node
	{
		public:
		using spnode=shared_ptr<node>;
		private:
		T value;
		spnode prev,next;
		public:
		node(T value,spnode prev,spnode next):value(value),prev(prev),next(next) {}
		static spnode make(T value,spnode prev,spnode next) { return make_shared<node>(value,prev,next); }
		spnode getPrev()const { return prev; }
		spnode getNext()const { return next; }
		T getValue()const { return value; }
		friend class List;
	};
	using spnode=shared_ptr<node>;
	private:
    spnode head,tail;
    spnode &refPrev(spnode node) { return node->prev?node->prev->next:head; }
    spnode &refNext(spnode node) { return node->next?node->next->prev:tail; }
    public:
    List() {}
    ~List() { clean(); }
	operator bool()const {return !isempty(); }
	bool isempty()const { return !head; }
	spnode first()const { return head; }
	spnode last()const { return tail; }
    List(const List &lst) { addtail(lst); }
    List &operator=(const List &lst)
    {
    	List<T> tmp(lst);
    	swap(lst);
    	return *this;
	}
	void swap(List &lst)
	{
		::swap(head,lst.head);
		::swap(tail,lst.tail);
	}
	void insertafter(spnode node,const List<T> &lst)
	{
		for(spnode i=lst.tail;i;i=i->prev) insertafter(node,i->value)
	}
	void insertafter(spnode node,T value)
	{
		if(node) node->next=refNext(node)=node::make(value,node,node->next);
		else addhead(value);
	}
	void insertbefore(spnode node,const List<T> &lst)
	{
		for(spnode i=lst.head;i;i=i->next) insertafter(node,i->value)
	}
	void insertbefore(spnode node,T value)
	{
		if(node) node->prev=refPrev(node)=node::make(value,node->prev,node);
		else addtail(value);
	}
	void remove(spnode node)
	{
		if(!node) return;
		refPrev(node)=node->next;
		refNext(node)=node->prev;
	}
	void clean()
	{
		while(head) remove(head);
	    tail=spnode{};
	}		
	void addtail(const List<T> &lst)
	{
		for(spnode i=lst.head;i;i=i->next) addtail(i->value);
	}
	void addtail(T value)
	{
		tail=(tail?tail->next:head)=node::make(value,tail,spnode{});
	}
	void addhead(const List<T> &lst)
	{
		for(spnode i=lst.tail;i;i=i->prev) addhead(i->value);
	}
	void addhead(T value)
	{
		head=(head?head->prev:tail)=node::make(value,spnode{},head);
	}
	spnode find(T value)
	{
		for(spnode i=head;i;i=i->next) if(i->value==value) return i;
		return spnode{};
	}
	ostream &print(ostream &s)const
	{
	   s<<"{ ";
	   for(spnode i=head;i;i=i->next) cout<<i->value<<" ";
	   return s<<"}";
	}
	ostream &tnirp(ostream &s)const // od tyłu
	{
	   s<<"{ ";
	   for(spnode i=tail;i;i=i->prev) cout<<i->value<<" ";
	   return s<<"}";
	}
	friend ostream &operator<<(ostream &s,const List<T> &lst) { return lst.print(s); }
};

void prn(const List<int> &lst)
{
   cout<<lst<<endl;
   lst.tnirp(cout)<<endl; // od tylu
   cout<<endl;
}

int main()
  {
   int i;
   List<int> lst;
   prn(lst);
   for(i=0;i<5;++i) lst.addtail(i);
   prn(lst);
   for(i=1;i<5;++i) lst.addhead(-i);
   prn(lst);
   lst.insertafter(lst.find(-1),-11);
   prn(lst);
   lst.insertbefore(lst.find(1),11);
   prn(lst);
   lst.insertafter(lst.last(),5);
   lst.insertbefore(List<int>::spnode{},6);
   prn(lst);
   lst.insertbefore(lst.first(),-5);
   lst.insertafter(List<int>::spnode{},-6);
   prn(lst);
   lst.remove(lst.find(0));
   prn(lst);
   lst.clean();
   prn(lst);
   cout<<endl;
   return 0;
  }
0

Ależ skomplikowaliście banalny temat.

0

Ja pragnę zwrócić uwagę, że w początkowym komentarzu jest specyfikacja (zapewne treść zadania).
Kod poniżej jest tylko podobny do specyfikacji i jej nie spełnia. Efekt jest taki, że jeśli nauczyciel ma testy automatyczne, to ten kod mu się nie skompiluje.
Zwracam uwagę na symbole:

  • element
  • cell

Powinno się zacząć od czegoś takiego: https://godbolt.org/z/hM6bsPEW3

1 użytkowników online, w tym zalogowanych: 0, gości: 1