<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Doppelt verkettete Liste als Ring]]></title><description><![CDATA[<p>CStoll schrieb:</p>
<blockquote>
<p>Bei deiner Liste solltest du auf jeden Fall einen Verweis von außen haben (z.B. einen Zeiger auf das erste Element). Dann kannst du von dort ausgehend an den Vorgänger- und Nachfolger-Zeigern entlanghangeln, um die benachbarten Elemente zu erreichen.</p>
</blockquote>
<p>Also eins Frage ich mich. Wieso wird überall bei der Implementierung ein Zeiger auf das erste (und evtl letzte) Element verwendet, also:</p>
<pre><code class="language-cpp">class List
{
    Node* first;
    Node* last;
};
</code></pre>
<p>Die Objekte direkt speichern geht doch auch und ist z.B. beim Implementieren von Iteratoren einfacher.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/289863/doppelt-verkettete-liste-als-ring</link><generator>RSS for Node</generator><lastBuildDate>Sat, 04 Apr 2026 16:13:55 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/289863.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 13 Jul 2011 23:07:08 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Wed, 13 Jul 2011 23:07:42 GMT]]></title><description><![CDATA[<p>CStoll schrieb:</p>
<blockquote>
<p>Bei deiner Liste solltest du auf jeden Fall einen Verweis von außen haben (z.B. einen Zeiger auf das erste Element). Dann kannst du von dort ausgehend an den Vorgänger- und Nachfolger-Zeigern entlanghangeln, um die benachbarten Elemente zu erreichen.</p>
</blockquote>
<p>Also eins Frage ich mich. Wieso wird überall bei der Implementierung ein Zeiger auf das erste (und evtl letzte) Element verwendet, also:</p>
<pre><code class="language-cpp">class List
{
    Node* first;
    Node* last;
};
</code></pre>
<p>Die Objekte direkt speichern geht doch auch und ist z.B. beim Implementieren von Iteratoren einfacher.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092505</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092505</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Wed, 13 Jul 2011 23:07:42 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Wed, 13 Jul 2011 23:19:23 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>Die Objekte direkt speichern geht doch auch und ist z.B. beim Implementieren von Iteratoren einfacher.</p>
</blockquote>
<p>Ich brauche mehr Details.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092509</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092509</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Wed, 13 Jul 2011 23:19:23 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Wed, 13 Jul 2011 23:27:15 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>314159265358979 schrieb:</p>
<blockquote>
<p>Die Objekte direkt speichern geht doch auch und ist z.B. beim Implementieren von Iteratoren einfacher.</p>
</blockquote>
<p>Ich brauche mehr Details.</p>
</blockquote>
<p>Meine Implementierung:</p>
<pre><code class="language-cpp">class List
{
    Node first; // Dummy-Node, VOR begin(), für rend()
    Node last; // Dummy-Node, Genau end()
};
</code></pre>
<p>Dadurch, dass hier immer 2 Nodes in der Liste sind, wird eine Leere Liste durch Verkettung der beiden Dargestellt.</p>
<p>Vorteile:<br />
- Einfügen findet immer in der Mitte statt, dadurch keine Anfangs/End-Checks auf ungültige Zeiger.<br />
- Iteratoren arbeiten immer auf Nodes. Bei einer Implementierung mit Zeigern und Anzahl an Nodes = Anzahl Elementen haben end() und rend() keine Nodes mehr. Hier muss getrickst werden.</p>
<p>Welche Argumente sprechen nun gegen diese Implementierung? Klar, hier werden ein paar Byte mehr Speicher verbraucht. Aber dafür hat man bessere Performance.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092510</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092510</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Wed, 13 Jul 2011 23:27:15 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Wed, 13 Jul 2011 23:42:50 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>volkard schrieb:</p>
<blockquote>
<p>314159265358979 schrieb:</p>
<blockquote>
<p>Die Objekte direkt speichern geht doch auch und ist z.B. beim Implementieren von Iteratoren einfacher.</p>
</blockquote>
<p>Ich brauche mehr Details.</p>
</blockquote>
<p>Meine Implementierung:</p>
<pre><code class="language-cpp">class List
{
    Node first; // Dummy-Node, VOR begin(), für rend()
    Node last; // Dummy-Node, Genau end()
};
</code></pre>
</blockquote>
<p>Nee:</p>
<pre><code class="language-cpp">template&lt;typename Data&gt;
class List
{
    struct Node
    {
       Node* prev;
       Node* pred;
       Data data;//Pfui!
    }
    Node first; // Dummy-Node, VOR begin(), für rend()
    Node last; // Dummy-Node, Genau end()
};
</code></pre>
<p>Aber Data hat keinen Standardkonstruktor UND Data hat ein static member Data::count, wo man jederzeit die Gesamtzahl der existierenden Data-Objekte abfragen kann, die geht um deine beiden Dummy-Objekte falsch.</p>
<blockquote>
<p>Vorteile:<br />
- Einfügen findet immer in der Mitte statt, dadurch keine Anfangs/End-Checks auf ungültige Zeiger.</p>
</blockquote>
<p>Du bist auf dem richtigen Weg. Aber EIN Dummy-Node reicht vollkommen aus, denn wir basteln einen Ring! Und dann mach das Problem noch weg, daß Dummy-Nodes Daten enthalten. Laß echte Nodes zum Beispiel von Dummy-Nodes erben.</p>
<blockquote>
<p>- Iteratoren arbeiten immer auf Nodes. Bei einer Implementierung mit Zeigern und Anzahl an Nodes = Anzahl Elementen haben end() und rend() keine Nodes mehr. Hier muss getrickst werden.</p>
</blockquote>
<p>Nö. Auch herkömmlich geht das sehr gut. end() kann ja schon {nullptr} sein.</p>
<blockquote>
<p>Welche Argumente sprechen nun gegen diese Implementierung? Klar, hier werden ein paar Byte mehr Speicher verbraucht. Aber dafür hat man bessere Performance.</p>
</blockquote>
<p>Wenn Du es richtig machst, wird kein Speicher verschwendet und für einen Container mit push-back/front und pop-back/front fallen ALLE Fallunterscheidungen weg. volkard mag sowas.</p>
<p>Aber das ist schon heftig getrickst, bis alles hübsch ist. Daher lieber erstmal bei der naiven Version bleiben. Und wenn man soweit ist, gerne die hübsche machen.<br />
Aber so ein Zwischending, nee, das mag ich nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092515</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092515</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Wed, 13 Jul 2011 23:42:50 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Wed, 13 Jul 2011 23:55:14 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>Aber Data hat keinen Standardkonstruktor</p>
</blockquote>
<p>Das ist doch eine Anforderung an einen Typen, der in einem Standardcontainer gespeichert werden soll, oder?</p>
<p>volkard schrieb:</p>
<blockquote>
<p>UND Data hat ein static member Data::count, wo man jederzeit die Gesamtzahl der existierenden Data-Objekte abfragen kann, die geht um deine beiden Dummy-Objekte falsch.</p>
</blockquote>
<p>Okay, das ist ein Argument. Vielleicht ein char-Array + placement-new in Node mit geeignetem Konstruktor. Wird aber dann durch die Data-Node ja gelöst.</p>
<p>volkard schrieb:</p>
<blockquote>
<p>Du bist auf dem richtigen Weg. Aber EIN Dummy-Node reicht vollkommen aus, denn wir basteln einen Ring!</p>
</blockquote>
<p>Finde ich ziemlich unintuitiv zu implementieren, aber wäre ein Möglichkeit, stimmt. Wer fragt auch die Library-Schreiber, was sie wollen.</p>
<p>volkard schrieb:</p>
<blockquote>
<p>Und dann mach das Problem noch weg, daß Dummy-Nodes Daten enthalten. Laß echte Nodes zum Beispiel von Dummy-Nodes erben.</p>
</blockquote>
<p>Dann müsste ich ja einen dynamic_cast zum Downcasten verwenden, wenn ich mich nicht täusche? Oder reicht in diesem Fall der static_cast? Ich habe so selten solche Casts verwendet, schon wieder alles vergessen...</p>
<p>volkard schrieb:</p>
<blockquote>
<p>Nö. Auch herkömmlich geht das sehr gut. end() kann ja schon {nullptr} sein.</p>
</blockquote>
<p>Davon hätte ich nun aber gerne eine Implementierung.</p>
<p>volkard schrieb:</p>
<blockquote>
<p>Wenn Du es richtig machst, wird kein Speicher verschwendet und für einen Container mit push-back/front und pop-back/front fallen ALLE Fallunterscheidungen weg. volkard mag sowas.</p>
</blockquote>
<p>Das kann durchaus sein. Meine Version ist keinesfalls perfekt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092520</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092520</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Wed, 13 Jul 2011 23:55:14 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 00:07:01 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>volkard schrieb:</p>
<blockquote>
<p>Du bist auf dem richtigen Weg. Aber EIN Dummy-Node reicht vollkommen aus, denn wir basteln einen Ring!</p>
</blockquote>
<p>Finde ich ziemlich unintuitiv zu implementieren, aber wäre ein Möglichkeit, stimmt. Wer fragt auch die Library-Schreiber, was sie wollen.</p>
</blockquote>
<p>Mach es doch mal. Du wirst sehen, daß deine Ressentiments völlig unbegründet sind.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092523</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092523</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 14 Jul 2011 00:07:01 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 00:10:09 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>volkard schrieb:</p>
<blockquote>
<p>Und dann mach das Problem noch weg, daß Dummy-Nodes Daten enthalten. Laß echte Nodes zum Beispiel von Dummy-Nodes erben.</p>
</blockquote>
<p>Dann müsste ich ja einen dynamic_cast zum Downcasten verwenden, wenn ich mich nicht täusche? Oder reicht in diesem Fall der static_cast? Ich habe so selten solche Casts verwendet, schon wieder alles vergessen...</p>
</blockquote>
<p>Schau in ein Buch und Du wirst herausfinden, daß Du für Downcasts (und hier liegt ein Downcast vor), dynamic_cast nehmen mußt. Aber Der Codex ist mehr eine Richtlinie und kein Gesetz. Hier reicht ausnahmsweise static_cast.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092525</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092525</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 14 Jul 2011 00:10:09 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 00:15:51 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>volkard schrieb:</p>
<blockquote>
<p>Nö. Auch herkömmlich geht das sehr gut. end() kann ja schon {nullptr} sein.</p>
</blockquote>
<p>Davon hätte ich nun aber gerne eine Implementierung.</p>
</blockquote>
<p>Hab ich was übersehen?</p>
<pre><code class="language-cpp">class DoubleLinkedList
{
   Node* begin,end;
   struct Iterator
   {
      Node* pos;
      Data&amp; operator*()
      {
         return pos-&gt;data;
      }
      void operator++()
      {
         pos=pos-&gt;pred;
      }
      friend bool operator==(Iterator a,.Iterator b)
      {
         return a.pos==b.pos;
      }
   }
   Iterator begin()
   {
      return Iterator(begin);
   }
   Iterator end()
   {
      return Iterator(0);
   }
</code></pre>
<p>Im Gegenzug hätte ich dann gerne Deine Liste zum Ring umgewandelt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092527</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092527</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 14 Jul 2011 00:15:51 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 01:57:32 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">#include &lt;utility&gt; // std::move
#include &lt;iostream&gt;

template &lt;typename T&gt;
class list
{
        struct node_base
        {
                node_base* next;
                node_base* prev;

                node_base()
                        : next(0)
                        , prev(0)
                {}
        };

        struct node : node_base
        {
                node(const T&amp; data)
                        : node_base()
                        , data(data)
                {}

                T data;
        };

        node_base anchor;

        void insert(node_base* pos, const T&amp; value)
        {
                pos-&gt;prev-&gt;next = new node(value);
                pos-&gt;prev-&gt;next-&gt;next = pos;
                pos-&gt;prev-&gt;next-&gt;prev = pos-&gt;prev;
                pos-&gt;prev = pos-&gt;prev-&gt;next;
        }

public:

        list()
        {
                anchor.next = &amp;anchor;
                anchor.prev = &amp;anchor;
        }

        void push_back(const T&amp; value)
        {
                insert(&amp;anchor, value);
        }

        void push_front(const T&amp; value)
        {
                insert(anchor.next, value);
        }

        friend std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const list&lt;T&gt;&amp; l)
        {
                os &lt;&lt; '[';
                for(const typename list&lt;T&gt;::node_base* node = &amp;l.anchor; node-&gt;next != &amp;l.anchor; node = node-&gt;next)
                        os &lt;&lt; ' ' &lt;&lt; static_cast&lt;const typename list&lt;T&gt;::node*&gt;(node)-&gt;data;
                return os &lt;&lt; &quot; ]&quot;;
        }
};

int main()
{
        list&lt;int&gt; l;
        l.push_back(42);
        l.push_back(666);
        l.push_back(123);

        std::cout &lt;&lt; l;
}
</code></pre>
<p>Ausgabe:</p>
<pre><code>[ 1536264460 42 666 ]
</code></pre>
<p><a href="http://ideone.com/QBv3O" rel="nofollow">http://ideone.com/QBv3O</a><br />
Naja fast <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092536</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092536</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Thu, 14 Jul 2011 01:57:32 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 01:38:03 GMT]]></title><description><![CDATA[<p>Ich hasse es, wenn ich Code von ideone erst hierher kopieren muß.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092537</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092537</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 14 Jul 2011 01:38:03 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 01:39:29 GMT]]></title><description><![CDATA[<p>Wollte, dass man die Ausgabe sieht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /><br />
Link nochmal dazu kopiert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092538</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092538</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Thu, 14 Jul 2011 01:39:29 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 01:45:09 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">friend std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const list&lt;T&gt;&amp; l)
        {
                os &lt;&lt; '[';
                for(const typename list&lt;T&gt;::node_base* node = l.anchor.next; node != &amp;l.anchor; node = node-&gt;next)
                        os &lt;&lt; ' ' &lt;&lt; static_cast&lt;const typename list&lt;T&gt;::node*&gt;(node)-&gt;data;
                return os &lt;&lt; &quot; ]&quot;;
        }
</code></pre>
<p>begin() ist natürlich nach dem anchor, nämlich das erste gültige element.<br />
und end() ist anchor, das dummy-element.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092539</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092539</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 14 Jul 2011 01:45:09 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 01:44:48 GMT]]></title><description><![CDATA[<p>Ich weiß, dass der falsch iteriert <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /><br />
Wollte es gerade beheben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092540</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092540</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Thu, 14 Jul 2011 01:44:48 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 01:50:43 GMT]]></title><description><![CDATA[<p>Eventuell sowas für die Kosmetik. Deinen Verzeigerungscode Code konnte ich nicht flüssig lesen.</p>
<pre><code class="language-cpp">void insert(node_base* pos, const T&amp; value)
        {
            node_base* newnode=new node(value);//knoten erzeugen

            newnode-&gt;prev=pos-&gt;prev;//knoten einstellen
            newnode-&gt;next=pos;

            newnode-&gt;prev-&gt;next=newnode;//ringbedingung reparieren
            newnode-&gt;next-&gt;prev=newnode;
        }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2092541</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092541</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 14 Jul 2011 01:50:43 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 02:01:34 GMT]]></title><description><![CDATA[<p>Bisher war das insert() die einzgie Funktion, die ich einmal geschrieben habe und nie wieder angesehen habe. Habe nie eine Methode gefunden, das schön zu formatieren. Deine ist aber gut, vielen Danke für den Tipp!</p>
<p>Hier nun die korrigierte Fassung:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

template &lt;typename T&gt;
class list
{
        struct node_base
        {
                node_base* next;
                node_base* prev;

                node_base()
                        : next(0)
                        , prev(0)
                {}
        };

        struct node : node_base
        {
                node(const T&amp; data)
                        : node_base()
                        , data(data)
                {}

                T data;
        };

        node_base anchor;

        void insert(node_base* pos, const T&amp; value)
        {
                node* new_node = new node(value);

                new_node-&gt;prev = pos-&gt;prev;
                new_node-&gt;next = pos;

                new_node-&gt;prev-&gt;next = new_node;
                new_node-&gt;next-&gt;prev = new_node;
        }

public:

        list()
        {
                anchor.next = &amp;anchor;
                anchor.prev = &amp;anchor;
        }

        void push_back(const T&amp; value)
        {
                insert(&amp;anchor, value);
        }

        void push_front(const T&amp; value)
        {
                insert(anchor.next, value);
        }

        friend std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const list&lt;T&gt;&amp; l)
        {
                os &lt;&lt; '[';
                for(const typename list&lt;T&gt;::node_base* node = l.anchor.next; node != &amp;l.anchor; node = node-&gt;next)
                        os &lt;&lt; ' ' &lt;&lt; static_cast&lt;const typename list&lt;T&gt;::node*&gt;(node)-&gt;data;
                return os &lt;&lt; &quot; ]&quot;;
        }
};

int main()
{
        list&lt;int&gt; l;
        l.push_back(42);
        l.push_back(666);
        l.push_back(123);

        std::cout &lt;&lt; l;
}
</code></pre>
<p>Hier mir Ausgabe: <a href="http://ideone.com/39StZ" rel="nofollow">http://ideone.com/39StZ</a></p>
<p>Gibt es hier eigentlich keine Spoiler? Wären echt praktisch.</p>
<p>Edit: Von der falschen Seite kopiert, Code + Link ausgebessert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092542</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092542</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Thu, 14 Jul 2011 02:01:34 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 02:28:05 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>Bisher war das insert() die einzgie Funktion, die ich einmal geschrieben habe und nie wieder angesehen habe. Habe nie eine Methode gefunden, das schön zu formatieren.</p>
</blockquote>
<p>Böser 314159265358979!</p>
<pre><code class="language-cpp">void insert_between(node_base* prev, node_base* next, const T&amp; value)
        {//Endlich Code, der offensichtlich richtig ist. 
            node_base* newnode=new node(value);
            newnode-&gt;prev=prev;
            newnode-&gt;next=next;
            prev-&gt;next=newnode;
            next-&gt;prev=newnode;
        }
        void push_back(const T&amp; value)
        {//Hier kommt der Ring-Charakter zum Tragen. Das hinteste Element ist anchor-&gt;prev, 
//also genau vor dem anchor. Eingefügt werden soll zwischen dem hintersten Element und dem end(). 
//end()==anchor. 
                insert_between(anchor.prev, &amp;anchor, value);
        }
        void push_front(const T&amp; value)
        {
                insert_between(&amp;anchor,anchor.next, value);
        }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2092543</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092543</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 14 Jul 2011 02:28:05 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 02:14:04 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">node_base()
                        : next(0)//müll
                        , prev(0)//müll
</code></pre>
<p>Das bringt doch nichts.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092545</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092545</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 14 Jul 2011 02:14:04 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 02:30:17 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">template &lt;typename T&gt;
class list
{
        struct node_base
        {
                node_base* next;
                node_base* prev;
        };

        struct node : node_base
        {
                node(const T&amp; data)
                        : data(data)
                {}

                T data;
        };

        node_base anchor;

	void insert_between(node_bast* left, node_base* right, const T&amp; value)
	{
		node_base* new_node = new node(value);

		new_node-&gt;prev = left;
		new_node-&gt;next = right;

		left-&gt;next = new_node;
		right-&gt;prev = new_node;
	}

public:

        list()
        {
                anchor.next = &amp;anchor;
                anchor.prev = &amp;anchor;
        }

        void push_back(const T&amp; value)
        {
                insert_between(anchor.prev, &amp;anchor, value);
        }

        void push_front(const T&amp; value)
        {
                insert_between(&amp;anchor, anchor.next, value);
        }

        friend std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const list&lt;T&gt;&amp; l)
        {
                os &lt;&lt; '[';
                for(const typename list&lt;T&gt;::node_base* node = l.anchor.next; node != &amp;l.anchor; node = node-&gt;next)
                        os &lt;&lt; ' ' &lt;&lt; static_cast&lt;const typename list&lt;T&gt;::node*&gt;(node)-&gt;data;
                return os &lt;&lt; &quot; ]&quot;;
        }
};
</code></pre>
<p>Verbessert. Vielen Dank für die Hilfe! Kannst du mir zeigen, wie man hier einen Allokator einbauen kann?</p>
<p>Edit: Der Destruktor fehlt natürlich auch noch. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092546</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092546</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Thu, 14 Jul 2011 02:30:17 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 02:36:02 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>Kannst du mir zeigen, wie man hier einen Allokator einbauen kann?</p>
</blockquote>
<p>Das will ich nicht.<br />
Es ist häßlich. Du mußt den Trick mit rebind raffen, denn du willst ja nicht Ts erzeugen, sondern nodes.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092547</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092547</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 14 Jul 2011 02:36:02 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 02:51:00 GMT]]></title><description><![CDATA[<p>Ich hab zwar keine Ahnung, was du mir damit sagen willst, aber es scheint zu funktionieren <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;memory&gt;

template
&lt;
        typename T,
        template &lt;typename&gt; class Allocator = std::allocator
&gt;
class list
{
        struct node_base
        {
                node_base* next;
                node_base* prev;
        };

        struct node : node_base
        {
                node(const T&amp; data)
                        : data(data)
                {}

                T data;
        };

        Allocator&lt;node&gt; allocator;
        node_base anchor;

        void insert_between(node_base* left, node_base* right, const T&amp; value)
        {
                node* new_node = allocator.allocate(1);
                allocator.construct(new_node, value);

                new_node-&gt;prev = left;
                new_node-&gt;next = right;

                left-&gt;next = new_node;
                right-&gt;prev = new_node;
        }

        void erase(node_base* pos)
        {
                pos-&gt;prev-&gt;next = pos-&gt;next;
                pos-&gt;next-&gt;prev = pos-&gt;prev;

                allocator.destroy(static_cast&lt;node*&gt;(pos));
                allocator.deallocate(static_cast&lt;node*&gt;(pos), 1);
        }

public:

        list()
        {
                anchor.next = &amp;anchor;
                anchor.prev = &amp;anchor;
        }

        ~list()
        {
                clear();
        }

        bool empty()
        {
                return anchor.next == &amp;anchor;
        }

        void push_back(const T&amp; value)
        {
                insert_between(anchor.prev, &amp;anchor, value);
        }

        void push_front(const T&amp; value)
        {
                insert_between(&amp;anchor, anchor.next, value);
        }

        void pop_back()
        {
                erase(anchor.prev);
        }

        void pop_front()
        {
                erase(anchor.next);
        }

        void clear()
        {
                while(!empty())
                        pop_back();
        }

        friend std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const list&lt;T&gt;&amp; l)
        {
                os &lt;&lt; '[';
                for(const typename list&lt;T&gt;::node_base* node = l.anchor.next; node != &amp;l.anchor; node = node-&gt;next)
                        os &lt;&lt; ' ' &lt;&lt; static_cast&lt;const typename list&lt;T&gt;::node*&gt;(node)-&gt;data;
                return os &lt;&lt; &quot; ]&quot;;
        }
};

int main()
{
        list&lt;int&gt; l;
        l.push_back(11);
        l.push_back(22);
        l.push_back(33);
        l.push_back(44);

        std::cout &lt;&lt; l;
}
</code></pre>
<p>Ausgabe:</p>
<blockquote>
<p>[ 11 22 33 44 ]</p>
</blockquote>
<p><a href="http://ideone.com/NXYEb" rel="nofollow">http://ideone.com/NXYEb</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092548</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092548</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Thu, 14 Jul 2011 02:51:00 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 03:22:02 GMT]]></title><description><![CDATA[<p>Du meinst sicher sowas, oder?</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

template &lt;typename T&gt; struct hugo;

template &lt;&gt;
struct hugo&lt;double&gt;
{
        static const double value = 3.14;
};

template &lt;&gt;
struct hugo&lt;char&gt;
{
        static const char value = 'P';
};

template &lt;typename, typename&gt; struct rebind;

template
&lt;
        template &lt;typename&gt; class Class,
        typename T1,
        typename T2
&gt;
struct rebind&lt;Class&lt;T1&gt;, T2&gt;
{
        typedef Class&lt;T2&gt; type;
};

int main()
{
        std::cout &lt;&lt; rebind&lt;hugo&lt;double&gt;, char&gt;::type::value;
}
</code></pre>
<p>Ausgabe: P</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092549</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092549</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Thu, 14 Jul 2011 03:22:02 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 11:54:43 GMT]]></title><description><![CDATA[<p>Das Verlinken kann man noch eleganter haben:</p>
<pre><code class="language-cpp">struct node_base
{
        node_base* next;
        node_base* prev;

        node_base()
                : next(this), prev(this)
        {}

        node_base(node_base* next)
                : next(next), prev(next-&gt;prev)
        {
                next-&gt;prev = this;
                prev-&gt;next = this;
        }

        ~node_base()
        {
                next-&gt;prev = prev;
                prev-&gt;next = next;
        }

private:

        node_base(const node_base&amp;);
        node_base operator=(const node_base&amp;);

};

template&lt;typename T&gt; 
struct node : node_base
{
        node(node_base* next, const T&amp; data)
                : node_base(next), data(data)
        {}

        T data;
};

template
&lt;
        typename T,
        typename Allocator = std::allocator&lt;T&gt;
&gt;
class list : private typename Allocator::template rebind&lt;node&lt;T&gt; &gt;::other // Höchstwahrscheinlich sowieso ein leeres Objekt, also müssen wir keinen Platz verschwenden
{

        typedef node&lt;T&gt; node_type;
        typedef typename Allocator::template rebind&lt;node_type&gt;::other allocator;

        allocator&amp; alloc()
        {
             return *this;
        }

        node_base anchor;

        void insert_before(node_base* right, const T&amp; value)
        {
                void* new_node = alloc().allocate(1);
                new (node) node_type(right, value);
        }

        void erase(node_base* pos)
        {
                node_type* this_node = static_cast&lt;node_type*&gt;(pos); // ein static_cast nach der Zerstörung führt zu UB
                this_node-&gt;~node_type();
                alloc().deallocate(this_node, 1);
        }

public:

        list()
                : anchor()
        {}

copy-ctor, copy-assignment, swap etc.
</code></pre>
<p>Ein in das Listobjekt eingebtterer Dummynode hat einen kleinen Nachteil: Wenn Iteratoren angeboten werden wird der end-Itertoren bei swap ungültig - das kann u.U. unangenehm sein, meist dürften aber die Vorteile überwiegen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092689</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092689</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 14 Jul 2011 11:54:43 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 17:17:55 GMT]]></title><description><![CDATA[<p>Als erstes verstehe ich das mit rebind überhaupt nicht. (Ich kenne das template nicht mal.)<br />
Außerdem finde ich, dass die list Klasse und nicht die node-Klasse für das Verketten zuständig sein sollte.<br />
Dann hast du hier ja placement-new und einen expliziten Destruktor-Aufruf verwendet. Ist das erlaubt, sollte man hier nicht die allocate und deallocate Funktionen verwenden?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092825</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092825</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Thu, 14 Jul 2011 17:17:55 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 17:43:02 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>Als erstes verstehe ich das mit rebind überhaupt nicht. (Ich kenne das template nicht mal.)</p>
</blockquote>
<p>Grob gesagt, die STL-Container übernehmen kein Template, sondern einen konkreten Typ, der in der Lage ist, den vorgegebenen Elementtyp zu verwalten. Da sie allerdings meistens keine reinen Objekte des Elementtyps speichern, sondern eigene Hilfsklassen (wie der node in eurem Beispiel), brauchen sie eine Möglichkeit, den Allokator nach seinem &quot;Bruder&quot; zu fragen:</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
class allocator
{
  ...
public:
  template&lt;typename U&gt;
  struct rebind
  {
    typedef allocator&lt;U&gt; type;
  };
  ...
};

template&lt;typename T, typename Alloc = std::allocator&lt;T&gt; &gt;
class List
{
  struct node
  {...};
  typedef typename Alloc::rebind&lt;node&gt;::type NodeAlloc; //Verwendung von rebind&lt;&gt;
  ...
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2092835</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092835</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Thu, 14 Jul 2011 17:43:02 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 17:47:56 GMT]]></title><description><![CDATA[<p>Okay, das muss man wissen, danke <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092836</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092836</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Thu, 14 Jul 2011 17:47:56 GMT</pubDate></item><item><title><![CDATA[Reply to Doppelt verkettete Liste als Ring on Thu, 14 Jul 2011 19:26:10 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>Außerdem finde ich, dass die list Klasse und nicht die node-Klasse für das Verketten zuständig sein sollte.</p>
</blockquote>
<p>Warum?</p>
<p>314159265358979 schrieb:</p>
<blockquote>
<p>Dann hast du hier ja placement-new und einen expliziten Destruktor-Aufruf verwendet. Ist das erlaubt, sollte man hier nicht die allocate und deallocate Funktionen verwenden?</p>
</blockquote>
<p>construct kann in C++0x lediglich zum Kopieren verwendet werden und die Benutzung dieser Funktionen ist nicht vorgeschrieben (außer evtl. für Container, die tatsächlich mit Ts arbeiten).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2092870</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2092870</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 14 Jul 2011 19:26:10 GMT</pubDate></item></channel></rss>