|
599 | 599 | "metadata": {},
|
600 | 600 | "outputs": [],
|
601 | 601 | "source": [
|
602 |
| - "# 7.17\n", |
603 |
| - "\"\"\"\n", |
604 |
| - "In the FavoritesListMTF class, we rely on public methods of the positional list ADT to move an element of a list at position p to become the first element of the list, while keeping the relative order of the remaining elements unchanged. Internally, that combination of operations causes one node to be removed and a new node to be inserted. Augment the PositionalList class to support a new method, move to front(p), that accomplishes this goal more directly, by relinking the existing node.\n", |
605 |
| - "\"\"\"\n", |
606 | 602 | "class FavouriteList:\n",
|
607 | 603 | " class _Item:\n",
|
608 | 604 | " __slots__ = '_value', '_count'\n",
|
609 | 605 | " def __init__(self, e):\n",
|
610 |
| - " self._value = e\n", |
611 |
| - " self._count = 0\n", |
| 606 | + " self._value = e #user's element\n", |
| 607 | + " self._count = 0 #access count\n", |
612 | 608 | " \n",
|
613 | 609 | " def _find_position(self, e):\n",
|
| 610 | + " #search for e and return its Position, None if not found.\n", |
614 | 611 | " walk = self._data.first()\n",
|
615 | 612 | " while walk is not None and walk.element()._value != e:\n",
|
616 | 613 | " walk = self._data.after(walk)\n",
|
617 | 614 | " return walk\n",
|
618 | 615 | " \n",
|
619 | 616 | " def _move_up(self, p):\n",
|
620 |
| - " if p != self._data.first():\n", |
| 617 | + " #move item at Position p earlier in the list based on access count.\n", |
| 618 | + " if p != self._data.first(): #if not 1st, then consider moving\n", |
621 | 619 | " cnt = p.element()._count\n",
|
622 | 620 | " walk = self._data.before(p)\n",
|
623 |
| - " if cnt > walk.element()._count:\n", |
624 |
| - " while (walk != self._data.first() and cnt > self._data.before(walk).element()._count):\n", |
| 621 | + " if cnt > walk.element()._count: #if cnt>, then proceed shifting forward\n", |
| 622 | + " while (walk != self._data.first() and cnt > self._data.before(walk).element()._count): #if still larger than before(walk), keep looping until walk cnt is larger than cnt\n", |
625 | 623 | " walk = self._data.before(walk)\n",
|
626 |
| - " self._data._add_before(walk, self._data.delete(p))\n", |
| 624 | + " self._data._add_before(walk, self._data.delete(p)) #after add before p, delete p in ori position\n", |
| 625 | + " \n", |
| 626 | + " def clear(self):\n", |
| 627 | + " pass\n", |
627 | 628 | " \n",
|
628 | 629 | " def __init__(self):\n",
|
629 | 630 | " self._data = PositionalList()\n",
|
|
635 | 636 | " return len(self._data)==0\n",
|
636 | 637 | " \n",
|
637 | 638 | " def access(self, e):\n",
|
638 |
| - " p = self._find_position(e)\n", |
| 639 | + " #user access e, therefore + e's access count\n", |
| 640 | + " p = self._find_position(e) #Locate existing e\n", |
639 | 641 | " if p is None:\n",
|
640 |
| - " p = self._data.add_last(self._Item(e))\n", |
| 642 | + " p = self._data.add_last(self._Item(e)) #add as last position, with Item within, that contains e and count\n", |
641 | 643 | " p.element()._count +=1\n",
|
642 |
| - " self._move_up(p)\n", |
| 644 | + " self._move_up(p) #check if p should move forward\n", |
643 | 645 | " \n",
|
644 | 646 | " def remove(self, e):\n",
|
645 | 647 | " p = self._find_position(e)\n",
|
646 | 648 | " if p is not None:\n",
|
647 | 649 | " self._data.delete(p)\n",
|
648 | 650 | " \n",
|
649 | 651 | " def top(self, k):\n",
|
| 652 | + " #generate sequence of top k elements in terms of access count\n", |
650 | 653 | " if not 1 <= k <= len(self):\n",
|
651 | 654 | " raise ValueError('Illegal value for k.')\n",
|
652 | 655 | " walk = self._data.first()\n",
|
653 | 656 | " for j in range(k):\n",
|
654 | 657 | " item = walk.element()\n",
|
655 |
| - " yield item._value\n", |
656 |
| - " walk = self._data.after(walk)\n", |
| 658 | + " yield item._value #report user's element\n", |
| 659 | + " walk = self._data.after(walk) #loop to next highest k-1 count\n", |
657 | 660 | "\n",
|
658 | 661 | "\n",
|
659 | 662 | "class FavouriteListMTF(FavouriteList):\n",
|
660 | 663 | "\n",
|
| 664 | + " #override _move_up to provide move-to-front heuristics\n", |
661 | 665 | " def _move_up(self, p):\n",
|
| 666 | + " # move accessed item at Position p to most front\n", |
662 | 667 | " if p != self._data.first():\n",
|
663 |
| - " self._data.add_first(self._data.delete(p))" |
664 |
| - ] |
665 |
| - }, |
666 |
| - { |
667 |
| - "cell_type": "code", |
668 |
| - "execution_count": null, |
669 |
| - "metadata": {}, |
670 |
| - "outputs": [], |
671 |
| - "source": [ |
672 |
| - "# 7.22\n", |
673 |
| - "\"\"\"\n", |
674 |
| - "Implement a clear( ) method for the FavoritesList class that returns the list to empty\n", |
675 |
| - "\"\"\"" |
676 |
| - ] |
677 |
| - }, |
678 |
| - { |
679 |
| - "cell_type": "code", |
680 |
| - "execution_count": null, |
681 |
| - "metadata": {}, |
682 |
| - "outputs": [], |
683 |
| - "source": [ |
684 |
| - "# 7.23\n", |
685 |
| - "\"\"\"\n", |
686 |
| - "Implement a reset counts( ) method for the FavoritesList class that resets all elements’ access counts to zero (while leaving the order of the list unchanged).\n", |
687 |
| - "\"\"\"" |
| 668 | + " self._data.add_first(self._data.delete(p)) #move to first, delete at ori p.\n", |
| 669 | + " \n", |
| 670 | + " #override top cause list is no longer sorted.\n", |
| 671 | + " def top(self, k):\n", |
| 672 | + " if not 1<=k<=len(self):\n", |
| 673 | + " raise ValueError('Illegal value for k')\n", |
| 674 | + "\n", |
| 675 | + " #make a copy\n", |
| 676 | + " temp = PositionalList()\n", |
| 677 | + " for item in self._data:\n", |
| 678 | + " temp.add_last(item)\n", |
| 679 | + " \n", |
| 680 | + " #repeatedly find, report and remove element with largest count.\n", |
| 681 | + " for j in range(k):\n", |
| 682 | + " highPos = temp.first()\n", |
| 683 | + " walk = temp.after(highPos)\n", |
| 684 | + " while walk is not None:\n", |
| 685 | + " if walk.element()._count>highPos.element()._count:\n", |
| 686 | + " highPos=walk\n", |
| 687 | + " walk = temp.after(walk)\n", |
| 688 | + " #now have found jth highest count\n", |
| 689 | + " yield highPos.element()._value\n", |
| 690 | + " temp.delete(highPos) #delete jth highest count, proceed to j+1th highest count (2nd highest count)\n" |
688 | 691 | ]
|
689 | 692 | }
|
690 | 693 | ],
|
|
0 commit comments