<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 494: Wrong runtime complexity for associative container's insert and delete</title>
<meta property="og:title" content="Issue 494: Wrong runtime complexity for associative container's insert and delete">
<meta property="og:description" content="C++ library issue. Status: NAD">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue494.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#NAD">NAD</a> status.</em></p>
<h3 id="494"><a href="lwg-closed.html#494">494</a>. Wrong runtime complexity for associative container's insert and delete</h3>
<p><b>Section:</b> 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a> <b>Status:</b> <a href="lwg-active.html#NAD">NAD</a>
 <b>Submitter:</b> Hans B os <b>Opened:</b> 2004-12-19 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="lwg-index-open.html#associative.reqmts">active issues</a> in [associative.reqmts].</p>
<p><b>View all other</b> <a href="lwg-index.html#associative.reqmts">issues</a> in [associative.reqmts].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD">NAD</a> status.</p>
<p><b>Discussion:</b></p>
<p>According to [lib.associative.reqmts] table 69, the runtime comlexity
of insert(p, t) and erase(q) can be done in amortized constant time.</p>

<p>It was my understanding that an associative container could be
implemented as a balanced binary tree.</p>

<p>For inser(p, t), you 'll have to iterate to p's next node to see if t
can be placed next to p.  Furthermore, the insertion usually takes
place at leaf nodes. An insert next to the root node will be done at
the left of the root next node</p>

<p>So when p is the root node you 'll have to iterate from the root to
its next node, which  takes O(log(size)) time in a balanced tree.</p>

<p>If you insert all values with insert(root, t) (where root is the
root of the tree before insertion) then each insert takes O(log(size))
time.  The amortized complexity per insertion will be O(log(size))
also.</p>

<p>For erase(q), the normal algorithm for deleting a node that has no
empty left or right subtree, is to iterate to the next (or previous),
which is a leaf node. Then exchange the node with the next and delete
the leaf node.  Furthermore according to DR 130, erase should return
the next node of the node erased.  Thus erasing the root node,
requires iterating to the next node.</p>

<p>Now if you empty a map by deleting the root node until the map is
empty, each operation will take O(log(size)), and the amortized
complexity is still O(log(size)).</p>

<p>The operations can be done in amortized constant time if iterating
to the next node can be done in (non amortized) constant time.  This
can be done by putting all nodes in a double linked list.  This
requires two extra links per node.  To me this is a bit overkill since
you can already efficiently insert or erase ranges with erase(first,
last) and insert(first, last).</p>



<p id="res-494"><b>Proposed resolution:</b></p>


<p><b>Rationale:</b></p>
<p>Only "amortized constant" in special circumstances, and we believe
  that's implementable. That is: doing this N times will be O(N), not
  O(log N).</p>





</body>
</html>
