IOS实行室第一次招新题目学习劳绩(均使用C++进行实现) ...

打印 上一主题 下一主题

主题 823|帖子 823|积分 2469

目录
一、关于蛇形矩阵
1.界说:
2.输入:
3.输出与释放:
二、有序单循环链表的插入
1.链表结构的构建:
2.输入:
 3.输出:
 4.释放:
5.目录:
 6.主函数:
*一些学到的新知识:
1.delete和free的区别:
2. nullptr和NULL的区别:
 三、类计划题目
1.基类和继承类
2. 基类的建立:
3.派生类的建立:
四、结语


一、关于蛇形矩阵

1.界说:

矩阵的输入输出一般使用二维数组,由于其列数和行数由控制台输入,所以要界说的是一个动态二维数组,如下所示:
  1. int rows , cols;
  2. cin >> rows >> cols;
  3. //定义:
  4. int **arr = new int *[rows];
  5. for(int i = 0 ; i < rows ; i++)
  6. {
  7.     arr[i] = new int [cols];
  8. }
复制代码
2.输入:

有了界说,下一步就是要思量怎样输入,通过观察蛇形矩阵的特点,思量边界条件和方向切换的情况,可以通过以下的方式进行输入:
  1. int rowStart = 0 , rowEnd = rows - 1;
  2. int colStart = 0 , colEnd = cols - 1;
  3. int num = 1;
  4. while (rowStart <= rowEnd && colStart <= colEnd)
  5. {
  6.     //行(从左到右输入):从 colStart 列到 colEnd 列
  7.     for (int i = colStart; i <= colEnd; i++)
  8.     {
  9.         arr[rowStart][i] = num;
  10.         num = num + 1;
  11.     }
  12.     rowStart = rowStart + 1;//(输入完一行,使得开始行数加一)
  13.     //列(从上往下输入):从 rowStart 行到 rowEnd 列
  14.     for (int i = rowStart; i <= rowEnd; i++)
  15.     {
  16.         arr[i][colEnd] = num;
  17.         num = num + 1;
  18.     }
  19.     colEnd = colEnd - 1;//(输入完一行,使得终止列数减一)
  20.     //行(从右到左输入):从 colEnd 列到 colStart 列
  21.     for (int i = colEnd; i >= colStart; i--)
  22.     {
  23.         arr[rowEnd][i] = num;
  24.         num = num + 1;
  25.     }
  26.     rowEnd = rowEnd - 1;//(输入完一行,使得终止行数减一)
  27.     //列(从下往上输入):从 rowEnd 行到 rowStart 列
  28.     for (int i = rowEnd; i >= rowStart; i--)
  29.     {
  30.         arr[i][colStart] = num;
  31.         num = num + 1;
  32.     }
  33.     colStart = colStart + 1;//(输入完一行,使得开始列数加一)
  34. }
复制代码
3.输出与释放:

接下来就是很通例的输出和内存的释放:
  1. //输出
  2. for(int i = 0 ; i < rows ; i++)
  3. {
  4.     for(int j = 0 ; j < cols ; j++)
  5.     {
  6.         cout << setw(3) << arr[i][j];//setw()用于控制输出格式
  7.     }
  8.     cout << endl;
  9. }
  10. //释放内存:
  11. for(int i = 0 ; i < rows ; i++)
  12. {
  13.     delete [] arr[i];
  14. }
  15. delete [] arr;
  16. arr = NULL;
复制代码
二、有序单循环链表的插入

关于链表,本次学习重要通过链表底子知识详解(非常详细简单易懂)-CSDN博客一文,下面是一些简单的感悟和代码誊写的思绪:
1.链表结构的构建:

(链表由一个个节点构成,每个节点一般接纳结构体的形式构造)
链表节点分为两个域
      数据域:存放各种现实的数据
      指针域:存放下一节点的首地点
  1. typedef struct Node
  2. {
  3.     //数据域
  4.     int data;
  5.     //指针域
  6.     struct Node* next;
  7. }node;
复制代码
2.输入:

  1. //node **p_head:使用指向指针的指针
  2. //原因:需要修改指向链表头部的指针。C++ 中的函数参数传递是值传递,
  3. //     即函数内对参数的修改不会影响到外部的实际参数。
  4. //     因此,如果想要在函数内修改外部的指针(比如修改链表头指针),就需要传入指针的指针,
  5. //     这样在函数内修改指针的指向就可以影响到外部的实际指针。
  6. //node *p_new:插入的新节点
  7. //原因:由于只需要修改新节点本身的数据域和指针域,并不需要修改该节点在外部的指向,
  8. //     所以直接传入指针即可
  9. void link_insert_data(node **p_head , node *p_new)
  10. {
  11.     //定义两个指针pb和pf,用来遍历链表。
  12.     node *pb,*pf;
  13.     //将pb和pf初始化为指向链表头部的指针
  14.     pb = pf = *p_head;
  15.     //链表为空链表:
  16.     if(*p_head == nullptr)
  17.     {
  18.         //新节点p_new作为链表的头节点
  19.         *p_head = p_new;
  20.         //将新节点的next指针置为nullptr,表示新节点是链表中的最后一个节点
  21.         p_new->next = nullptr;
  22.         return;
  23.     }
  24.     //链表非空链表:
  25.     //查找新节点应该插入的位置
  26.     while((p_new->data >= pb->data)  && (pb->next !=nullptr) )
  27.     {
  28.         pf = pb;
  29.         pb = pb->next;//继续向后遍历
  30.     }
  31.     //找到一个节点的num比新来的节点num大,插在pb的前面
  32.     if(p_new->data < pb->data)
  33.     {
  34.         //找到的节点是头节点,插在最前面
  35.         if(pb == *p_head)
  36.         {
  37.             p_new->next = *p_head;
  38.             *p_head = p_new;
  39.         }
  40.         //找到的节点不是头节点,将新节点插入到找到的节点(pf所指)之前。
  41.         else
  42.         {
  43.             pf->next = p_new;
  44.             p_new->next = pb;
  45.         }
  46.     }
  47.     //没有找到比新节点数据(p_new->data)大的节点,则新节点应该插在链表的最后
  48.     else
  49.     {
  50.         pb->next = p_new;
  51.         p_new->next = nullptr;
  52.     }
  53. }
复制代码
  1. //大概还可以写成:(是一些尝试过程中的产物)
  2. //输入不太一样,但效果应该差不多
  3. void insertInSortedCircularLinkedList(node *head, int value)
  4. {
  5.     node *p_new = new Node();
  6.     p_new->data = value;
  7.     p_new->next = nullptr;
  8.     if (head == nullptr)
  9.     {
  10.         // 空链表情况
  11.         head = p_new;
  12.         p_new->next = p_new;  // 让新节点指向自身,构成循环
  13.     }
  14.     else if (value <= head->data)
  15.     {
  16.         // 新节点的值比头节点小或等于头节点的值,插入到头部
  17.         p_new->next = head;
  18.         node *last = head;
  19.         while (last->next != head)
  20.         {
  21.             last = last->next;  // 找到最后一个节点
  22.         }
  23.         last->next = p_new;  // 更新尾节点的 next 指针
  24.         head = p_new;  // 更新头节点
  25.     }
  26.     else
  27.     {
  28.         // 中间或尾部插入
  29.         node *current = head;
  30.         while (current->next != head && current->next->data < value)
  31.         {
  32.             current = current->next;
  33.         }
  34.         p_new->next = current->next;
  35.         current->next = p_new;
  36.     }
  37. }
  38. 或者:
  39. node* insertInSortedCircularLinkedList(node *head, int value)
  40. {
  41.     node* newNode = new Node();
  42.     //使用 new 运算符在堆内存中动态分配了一个 Node 类型的对象,并将返回的地址赋给指针 newNode
  43.     newNode->data = value;
  44.     if (head == nullptr)
  45.     {
  46.         newNode->next = newNode;
  47.         return newNode;
  48.     }
  49.     node* pb = head ;
  50.     node* pf = nullptr;
  51.     do
  52.     {
  53.         pf = pb;
  54.         pb = pb->next;
  55.     }
  56.     while (pb != head && newNode->next >= pb->data);
  57.     if (pb == head)
  58.     {
  59.         newNode->next = head;
  60.         pf->next = newNode;
  61.         return newNode;
  62.     }
  63.     pf->next = newNode;
  64.     newNode->next = pb;
  65.     return head;
  66. }
复制代码
 3.输出:

  1. void link_print(node *head)
  2. {
  3.     if (head == nullptr)
  4.     {
  5.         cout << "链表为空" << endl;
  6.         return;
  7.     }
  8.     node *p_mov;
  9.     //定义新的指针保存链表的首地址,防止使用head改变原本链表
  10.     p_mov = head;
  11.     //当指针回到头结点时,表示已经遍历完整个循环链表
  12.     //当指针保存最后一个结点的指针域为nullptr时,循环结束
  13.     while(p_mov != nullptr)
  14.     {
  15.         //先打印当前指针保存结点的指针域
  16.         cout << p_mov->data << " ";
  17.         //指针后移,保存下一个结点的地址
  18.         p_mov = p_mov->next;
  19.     }
  20.     cout << endl;
  21. }
复制代码
  1. //也可以写成do-while 循环的形式,效果一样
  2. do
  3. {
  4.     //先打印当前指针保存结点的指针域
  5.     cout << p_mov -> data << " ";
  6.     //指针后移,保存下一个结点的地址
  7.     p_mov = p_mov -> next;
  8. } while(p_mov != head);
复制代码
 4.释放:

  1. //加入之后会使退出变得非常卡顿,在此留疑
  2. void freeCircularLinkedList(node* head)
  3. {
  4.     if (head == nullptr)
  5.     {
  6.         return;
  7.     }
  8.     //定义一个指针变量保存头结点的地址
  9.     node* current = head;
  10.     node* temp;
  11.     do{
  12.         temp = current;
  13.         current = current -> next;
  14.         delete temp;
  15.     } while (current != head);
  16. }
复制代码
5.目录:

  1. void menu(node*& head)
  2. {
  3.     cout << "******  Data Structure  ******" << endl;
  4.     cout << "1——有序插入单列表" << endl;
  5.     cout << "2——查看单列表" << endl;
  6.     cout << "     退出,请输入0" << endl;
  7.     int sel;
  8.     while(cin >> sel)
  9.     {
  10.         if(sel == 0)
  11.         {
  12.             //freeCircularLinkedList(head);
  13.             cout << endl << "期待您的下次使用!" ;
  14.             break;
  15.         }
  16.         switch(sel)
  17.         {
  18.         case 1:
  19.         {
  20.             node* p_new = new Node();//申请一个新节点
  21.             cout << "请输入要插入的值:"; //给新节点赋值
  22.             cin >> p_new->data;
  23.             p_new->next = nullptr;
  24.             link_insert_data(&head,p_new);
  25.             break;
  26.         }
  27.         case 2:
  28.         {
  29.             link_print(head);
  30.             break;
  31.         }
  32.         default:
  33.         {
  34.             cout << endl;
  35.             cout << "您输入数字有误,请重新输入:";
  36.             break;
  37.         }
  38.         }
  39.     }
  40. }
复制代码
 6.主函数:

  1. int main()
  2. {
  3.     node* head = nullptr;
  4.     menu(head);
  5.     return 0;
  6. }
复制代码
*一些学到的新知识:

1.delete和free的区别:

   delete 和 free 是释放内存的两种方式,重要用于释放动态分配的内存,但在 C++ 和 C 语言中有一些区别:
  delete:
  delete 是 C++ 中的关键字,用于释放使用 new 运算符动态分配的单个对象或对象数组的内存。
delete 会调用对象的析构函数,然后释放内存空间。
使用 delete 释放指向对象的指针后,指针会主动设置为 nullptr。
不能用 delete 来释放使用 malloc() 或 calloc() 分配的内存。
  free:
  free 是 C 语言中的函数,用于释放动态分配的内存。
free 只是简单地释放内存,不会调用任何析构函数。
调用 free 后,指针并不会被主动置空,可能会导致野指针问题。
不能用 free 来释放使用 new 运算符分配的内存。
总的来说,如果在 C++ 中动态分配了内存,应该使用 delete 进行释放;在 C 语言中动态分配内存则应使用 free 进行释放。在 C++ 中,最好避免混合使用 new/delete 和 malloc/free,以避免因为差别的释放方式导致的问题。
  2. nullptr和NULL的区别:

   在C++中,nullptr 是 C++11 中引入的空指针常量,用于表示空指针。而 NULL 在较早的 C++ 尺度中就存在,通常被界说为宏或者整数 0,也用于表示空指针。
  区别:
  

  • nullptr 是 C++11 引入的空指针常量,具有明白的空指针类型,可以隐式转换为任意指针类型,且不会与整数 0 肴杂。
  • NULL 在较早的 C++尺度中就存在,通常被界说为宏或者整数 0,可能会与整数 0 肴杂,不具有明白的空指针类型。
  *最好使用nullptr 来表示空指针,因为它更加明白和安全,避免了与整数 0 的肴杂。
   三、类计划题目

1.基类和继承类

在写此题目之前,必要提前了解什么是基类和继承类,本次学习通过Th3.11:基类与派生类关系之详细再讨论_派生类是基类的子集-CSDN博客一文了解,在此仅简述其运用方法:
   class Dad {};
class Son : public Dad {};
  
  //C++中给出了final关键字,可以防止误用了不想当基类的类作为基类
  类型1
class Dad  final {//让不想做基类的Dad类声明为final的!
public:
/*...*/
};
class Son : public Dad {//错误!Dad不能用作基类
public:
/*...*/
};
类型2
class Dad {
public:
/*...*/
};
class Son final : public Dad {//让不想做基类的Son类声明为final的!
public:
/*...*/
};
class GrandSon:public Son{//错误!Son不能用作基类
public:
/*...*/
}
  多余不再赘述
2. 基类的建立:

  1. #ifndef ACCOUNT_H
  2. #define ACCOUNT_H
  3. using namespace std;
  4. class Account
  5. {
  6. private:
  7.     double balance;
  8. public:
  9.     Account()
  10.     {
  11.     }
  12.     Account(double Balance)
  13.     {
  14.         if (Balance >= 0)
  15.         {
  16.             balance = Balance;
  17.         }
  18.         else
  19.         {
  20.             balance = 0;
  21.             cout << "\t\t该初始化余额是一个无效的值,已将账户余额定义为0" << endl;
  22.         }
  23.     }
  24.     ~Account()
  25.     {
  26.     }
  27.     void credit(double amount)
  28.     {
  29.         balance = balance + amount;
  30.     }
  31.     void debit(double amount)
  32.     {
  33.         if (amount > balance)
  34.         {
  35.             cout << endl << "\t\tDebit amount exceeded account Balance." << endl;
  36.         }
  37.         else
  38.         {
  39.             balance = balance - amount;
  40.         }
  41.     }
  42.     double getBalance() const
  43.     {
  44.         return balance;
  45.     }
  46. };
  47. #endif // ACCOUNT_H
复制代码
3.派生类的建立:

  1. #ifndef SAVINGSACCOUNT_H
  2. #define SAVINGSACCOUNT_H
  3. #include "Account.h"
  4. using namespace std;
  5. class SavingsAccount : public Account
  6. {
  7. private:
  8.     double Rate;
  9.     int Year;
  10. public:
  11.     SavingsAccount()
  12.     {
  13.     }
  14.     SavingsAccount(double Balance , double rate , int year) :
  15.                   Account(Balance) , Rate(rate) , Year(year){}
  16.     ~SavingsAccount()
  17.     {
  18.     }
  19.     double calculate()
  20.     {
  21.         double total = getBalance();
  22.         for (int i = 1; i <= Year; i++)
  23.         {
  24.             double interest = total * Rate * 0.01;
  25.             total = total + interest;
  26.         }
  27.         return total;
  28.     }
  29. };
  30. #endif // SAVINGSACCOUNT_H
复制代码
4.主函数的建立:
(利用C++中的控制台界面来实现可视化菜单操纵(大概可以算是某种程度上的可视化))
  1. #include <iostream>
  2. #include "SavingsAccount.h"
  3. using namespace std;
  4. void menu(SavingsAccount &account)
  5. {
  6.     system("cls");
  7.     cout << "\t\t************************************" << endl;
  8.     cout << "\t\t当前余额为:" << account.getBalance() << endl;
  9.     cout << "\t\t************************************" << endl;
  10.     cout << "\t\t******  1.存款                ******" << endl;
  11.     cout << "\t\t******  2.取款                ******" << endl;
  12.     cout << "\t\t******  3.算存款之后的总余额  ******" << endl;
  13.     cout << "\t\t******  0.退出                ******" << endl;
  14.     cout << "\t\t************************************" << endl;
  15.     cout << "\t\t请输入您的选择:";
  16. }
  17. int main()
  18. {
  19.     double Balance , amount;
  20.     cout << "\t\t创建一个账户,并输入初始余额:";
  21.     cin >> Balance;
  22.     cout << endl;
  23.     SavingsAccount account(Balance , 0 , 0);
  24.     system("pause");//请按任意键继续
  25.     menu(account);
  26.     int sel;
  27.     while(cin >> sel)
  28.     {
  29.         cout << endl;
  30.         if(sel == 0)
  31.         {
  32.             cout << "\t\t期待您的下次使用!" ;
  33.             exit(0);
  34.             //exit(0)函数可以立即终止程序的执行,并返回给操作系统。
  35.             //参数0表示正常退出,非零值表示异常退出
  36.         }
  37.         switch(sel)
  38.         {
  39.         case 1:
  40.             cout << "\t\t请输入存款金额:";
  41.             cin >> amount;
  42.             account.credit(amount);
  43.             cout << endl;
  44.             system("pause");//请按任意键继续
  45.             menu(account);
  46.             break;
  47.         case 2:
  48.             cout << "\t\t请输入取款金额:";
  49.             cin >> amount;
  50.             account.debit(amount);
  51.             cout << endl;
  52.             system("pause");//请按任意键继续
  53.             menu(account);
  54.             break;
  55.         case 3:
  56.             double rate;
  57.             int year;
  58.             cout << "\t\t请输入存款年利率(单位:%):";
  59.             cin >> rate;
  60.             cout << "\t\t请输入存款年份:";
  61.             cin >> year;
  62.             cout << endl;
  63.             account = SavingsAccount(account.getBalance() , rate , year);
  64.             cout << "\t\t账户经过" << year <<
  65.                    "年(年利率为:" << rate << ")后,账户的总余额为:" <<
  66.                    account.calculate() << endl;
  67.             cout << endl;
  68.             system("pause");//请按任意键继续
  69.             menu(account);
  70.             break;
  71.         default:
  72.             cout << "\t\t您输入数字有误,请重新输入:";
  73.             break;
  74.         }
  75.     }
  76.     return 0;
  77. }
复制代码
*本来想实行一下改配景颜色,但是不太好看就没改,在此附上修改方式,参考c++可视化操纵(一)——控制台点击型菜单(windows.h)-CSDN博客一文
   #include <Windows.h>
  
  //配景白色
  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(handle, BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
  
// 将文本颜色设置为淡蓝色
  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(handle, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
  四、结语

本次学习到此竣事啦,虽然可能程序上另有很多的不敷(欢迎各位指正),还是感谢各位可以看我写到这里。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

慢吞云雾缓吐愁

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表