• 【Weiss】【第03章】练习3.4、3.5:有序链表求交、并


    【练习3.4】

    给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∩L2的过程。

    【练习3.5】

    给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∪L2的过程。

    思路比较简单,测试代码如下,两道题比较相似,测试代码就放一起了。

     1 #include <iostream>
     2 #include "linklist.h"
     3 using namespace std;
     4 using namespace linklist;
     5 template class List<int>;
     6 int main(void)
     7 {
     8     List<int> primer;
     9 
    10     //原始链表
    11     cout << "/*additem()*/" << endl;
    12     primer.additem(2);
    13     primer.additem(3);
    14     primer.additem(5);
    15     primer.additem(7);
    16     primer.additem(8);
    17     primer.additem(11);
    18     primer.additem(13);
    19     primer.additem(17);
    20     primer.additem(23);
    21     primer.additem(24);
    22     primer.traverse();
    23     cout << "
    /*end*/
    
    " << endl;
    24 
    25     //测试求交
    26     cout << "/*intersection()*/" << endl;
    27     List<int> odd;
    28     odd.additem(3);
    29     odd.additem(5);
    30     odd.additem(7);
    31     odd.additem(9);
    32     odd.additem(11);
    33     odd.additem(13);
    34     odd.additem(15);
    35     odd.additem(17);
    36     odd.additem(19);
    37     odd.additem(21);
    38     odd.additem(23);
    39     odd.additem(25);
    40     odd.additem(27);
    41     odd.additem(29);
    42     odd.traverse();
    43     cout <<"
    "<<flush;
    44     odd.intersecton(primer);
    45     odd.traverse();
    46     cout << "
    /*end*/
    
    " << endl;
    47 
    48     //测试求并
    49     cout << "/*join()*/" << endl;
    50     List<int> natural;
    51     natural.additem(1);
    52     natural.additem(2);
    53     natural.additem(4);
    54     natural.additem(8);
    55     natural.additem(16);
    56     natural.traverse();
    57     cout << endl;;
    58     natural.join(primer);
    59     natural.traverse();
    60     cout << "
    /*end*/
    
    " << endl;
    61 
    62     system("pause");
    63 }
    View Code

    主要思路就是两个链表同时前进并比较元素大小,在合适的节点处删除或插入节点,时间复杂度O(n)。

    为了满足中途插入或删除的需求,在3.4处补充了一个最初没有的辅助删除操作,3.5补充了一个辅助插入操作。

    练习3.4,求交代码如下:

     1 //练习3.4新增,删除指定地址的下一个节点,如地址为nullptr,则删除头节点
     2 template <typename T> bool List<T>::remove(Node<T>* pos)
     3 {
     4     if (length == 0)
     5     {
     6         cout << "No data!" << endl;
     7         return false;
     8     }
     9     if (pos == nullptr)
    10     {
    11         pos = front;
    12         front = front->next;
    13         delete pos;
    14     }
    15     else
    16     {
    17         Node<T>* temp = pos->next;
    18         pos->next = pos->next->next;
    19         delete temp;
    20     }
    21     --length;
    22     return true;
    23 }
    24 //练习3.4新增,计算两升序链表元素交集并直接覆盖在原链表上
    25 template <typename T> void List<T>::intersecton(List<T> inorder)
    26 {
    27     //原表多保存一个prev以删除节点时传参用
    28     Node<T>* curr = front;
    29     Node<T>* prev = nullptr;
    30     Node<T>* curr2 = inorder.front;
    31     while (curr != nullptr && curr2 != nullptr)
    32     {
    33         //原表元素小于新表,删除原表元素
    34         if (curr->data < curr2->data)
    35         {
    36             curr = curr->next;
    37             remove(prev);
    38         }
    39         //新表元素大于原表,新表查看下一个节点
    40         else if (curr2->data < curr->data)
    41             curr2 = curr2->next;
    42         //两表元素相等,指针共同后移,保留元素
    43         else
    44         {
    45             prev = curr;
    46             curr = curr->next;
    47             curr2 = curr2->next;
    48         }
    49     }
    50     //如果新链表结束后,原链表尾部还有元素,全部删除
    51     while (curr != nullptr)
    52     {
    53         curr = curr->next;
    54         remove(prev);
    55     }
    56 }

    练习3.5,求并代码如下:

     1 //练习3.5新增,增加一个节点于在指定地址的下一个节点,如地址为nullptr,则于头节点插入
     2 template <typename T> bool List<T>::additem(const T &item, Node<T> *pos)
     3 {
     4     Node<T>* pnew = new Node<T>(item);
     5     if (pos == nullptr)
     6     {
     7         pnew->next = front;
     8         front = pnew;
     9     }
    10     else
    11     {
    12         pnew->next = pos->next;
    13         pos->next = pnew;
    14     }
    15     ++length;
    16     return true;
    17 } 
    18 //练习3.5新增,计算两升序链表元素并集并直接覆盖在原链表上
    19 template <typename T> void List<T>::join(List<T> inorder)
    20 {
    21     Node<T>* curr = front;
    22     Node<T>* prev = nullptr;
    23     Node<T>* curr2 = inorder.front;
    24     while (curr != nullptr && curr2 != nullptr)
    25     {
    26         //原链表元素小于新链表元素,原链表查看下一个节点
    27         if (curr->data < curr2->data)
    28         {
    29             prev = curr;
    30             curr = curr->next;
    31         }
    32         //新链表元素小于原链表元素,则插入一个带相同值的元素在curr前(即在prev后)
    33         else if (curr2->data < curr->data)
    34         {
    35             additem(curr2->data, prev);
    36             //因为是在prev指针【后】插入元素,为保证升序,插入后prev向后移动
    37             if (prev == nullptr)
    38                 prev = front;
    39             else
    40                 prev = prev->next;
    41             curr2 = curr2->next;
    42         }
    43         //两元素相等,共同查看下一个节点
    44         else
    45         {
    46             prev = curr;
    47             curr = curr->next;
    48             curr2 = curr2->next;
    49         }
    50     }
    51     while (curr2 != nullptr)
    52     {
    53         additem(curr2->data, prev);
    54         if (prev == nullptr)
    55             prev = front;
    56         else
    57             prev = prev->next;
    58         curr2 = curr2->next;
    59     }
    60 }
  • 相关阅读:
    git创建分支与合并分支
    web实现点击左侧导航,右侧加载不同的网页(这种布局多用于后台管理系统)
    小程序通过用户授权获取手机号之getPhoneNumber
    git 本地仓库与远程仓库建立连接
    multipartUpload上传图片到阿里云
    5月23日——SPA单页面应用的原理
    5月23日——谈谈对BFC规范的理解
    5月11日——IOS下如何检测用户是否安装微信
    5月10日——华为内置虚拟键问题
    移动端WEB开发,click,touch,tap事件浅析
  • 原文地址:https://www.cnblogs.com/catnip/p/4329164.html
Copyright © 2020-2023  润新知