根据要求补充代码,给出运行结果即可!.
代码一:
//理解C++基类对象和子类对象之间的类型适应原理和函数覆盖的语法,补全代码后,实现和预期测试集相同的输出效果。
#include<iostream>
using namespace std;
//C++的类型适应机制
//在C++中,子类对象与基类对象的微秒关系有三种。
//1.子类对象可以作为基类对象来使用。
//2.基类指针可以指向子类对象。
//3.基类引用可以引用子类对象。
class Point {
public:
Point(int xa, int yb) { //有参构造函数
x = xa;
y = yb;
}
//补全代码,完成显示图形的函数的定义。
//---------------------------------
}
protected:
int x; //x坐标
int y; //yx坐标
};
class Square : public Point{
public:
Square(int xa, int xb, int len):Point(xa,xb),length(len){
}
//补全代码,完成显示正方形的函数的定义。
//---------------------------------
protected:
int length;
};
class Circle: public Point {
public:
Circle(int xa, int xb, int r):Point(xa,xb) {
radius = r;
}
//补全代码,完成显示圆形的函数的定义。
//---------------------------------
protected:
int radius;
};
int main() {
//子类Circle对象c
Circle c(1, 1, 2);
//子类Square对象s
Square s(0, 0, 3);
//基类Point对象p,由子类对象构造
Point p(c);
//展示p数据
p.display();
//展示c数据
c.display();
//补全代码,使基类指针pp,指向c,并显示c坐标
//-------------------------------------
//补全代码,使基类引用f,引用c,并显示c坐标
//-------------------------------------
return 0;
}
//测试输入:
//预期输出:
//调用Point的display函数,显示一个点.
//坐标:(1, 1)
//调用Circle的display函数,显示一个圆.
//坐标:(1, 1), 半径:2
//调用Point的display函数,显示一个点.
//坐标:(1, 1)
//调用Point的display函数,显示一个点.
//坐标:(1, 1)
代码二:
//编写一个C++的链表类,完成链表数据的增加,删除,修改,查询操作,并利用主函数验证程序正确性。
#include <iostream>
using namespace std;
//结点结构
struct Node {
int data; //这个整型变量代表结点携带的数据
Node *next; //指向下一个结点的链表指针(保存着下一个结点的地址)
};
//定义一个处理链表的类
//该类像一个工具包,里面放着各种处理链表的工具,以及链表的数据。
class LinkList {
public:
//构造函数对链表的结构进行初始化,利用new,构建第一个结点。
LinkList() {
//补全代码,完成对头结点的初始化工作。
//新建一个结点(在堆内存中申请一个结点的空间,并将地址返回给first指针,该结点本身是空结点,仅做头结点用)
//将该结点的next指针清空(可以理解为封口,堵头儿,将来遍历的时候,有个到此为止的标记)
//------------------------------------------------
}
//析构函数。
~LinkList();
//插入一个新结点,该结点携带数据x,插入后成为该链表的第i个结点。
void Insert(int i,int x);
//搜索结点,搜索携带数据为x的结点,返回该结点所在的索引号(该结点是第几个结点),未找到则返回0
int Search(int x);
//获取第i个结点的数据,如果未找到,则返回0。
int Get(int i);
//删除第i个结点。
void Delete(int i);
//求链表的长度,也就是链表结点的个数。
int Length();
//打印链表的数据。
void PrintList();
private:
//链表头结点指针,也就是第一个结点的地址。
Node *first;
};
//插入一个新结点,该结点携带数据x,插入后成为该链表的第i个结点。
void LinkList::Insert(int i, int x) {
//结点指针p作为游标指针,从头开始遍历链表,找到要插入的位置。
Node *p;
//结点指针s为新结点指针,通过new构建新结点,插入到链表的正确位置。
Node *s;
//用来计算遍历的位置,直至i的前一个位置为止。
int j;
//插入算法开始:
//首先,讲游标指针p指向头结点。(first为本类唯一的一个属性,就是头结点的地址)
p = first;
//遍历位置游标j从0开始。
j = 0;
//当游标p有意义(也就是指向了一个存在的结点,不为空),
//并且位置游标j没到第i个
while(p && j < i - 1) {
//就继续向后寻找,遍历。
p = p->next;
//位置游标j也向后增加
j++;
//直到p为空(也就是到了链表末尾)或者j已挪动到预定位置i的前一个位置为止。
}
//此时,退出上述while循环,有两种可能:
//(1)p到末尾;
//(2)j到达预定位置,即i的前一个位置。
//如果此时p到末尾,或者i位置是个不合理位置。那报错。
if(!p || i < 1)
{
cout << "位置不正确" << endl;
}
//如果此时p没到末尾,则必定到达了预定位置(i-1)。
//所以,可以生成新结点s,并将结点连接到原来i的位置,也就是现在的p->next的位置
//并将p的next指针指向s,完成插入操作。
//注意,一定是先将新结点尾部挂接在原链表上,再拆开原链表,将前一部分挂接在
//新结点上,组成一个新链表。
else
{
//补全代码,完成新结点的产生和插入操作。
//产生新结点,并填上数据x
//新结点尾部指向当前位置的后方,完成挂接。
//以当前位置为分界,原链表拆开,前一部分尾部挂接在新结点上,组成新链表。
//------------------------------------------------------------
}
}
//搜索结点,搜索携带数据为x的结点,返回该结点所在的索引号(该结点是第几个结点)
//未找到则返回0
int LinkList::Search(int x) {
//结点指针p作为游标指针,从头开始遍历链表
Node *p;
//j记录结点的索引位置
int j;
//算法开始:
//首先,将p指向有意义的第一个结点(也就是索引为1的结点,也是实际的第二个结点)
p = first->next;
//j记录为1(从0开始的)
j = 1;
//只要p未到末尾
while(p)
{
//补全代码,完成值为x的结点的查找
//考查游标p指向的结点,如果该结点恰好携带数据x,则退出循环,找到了。
//如果该结点数据并不是x,则p继续向后遍历下一个结点继续考查
//------------------------------------------------------
//索引值也随之后移。
j++;
}
//如果上述循环正常退出,则p到末尾,也就是没找到
if(!p)
//则返回0,表示未找到。有效的索引值从1开始。
return 0;
//如果上述循环没正常退出,也就是break被激活,那定然是找到了x结点。
else
//则将当时记录的索引j返回。交差成功。
return j;
}
//获取第i个结点的数据,如果未找到,则返回0。
int LinkList::Get(int i) {
//首先,将游标p指向有意义的第一个结点(也就是索引为1的结点,也是实际的第二个结点)
Node *p = first->next;
//j记录为1(从0开始的)
int j = 1;
//补全代码,实现结点的获取。
//向后移动游标,直至i结点(也就是j==i时,退出,如果此时的p仍然有意义的话)
//提示,游标p后移同时,索引j也应后移。
//-------------------------------------------------------------
//如果p到末尾退出的,那证明没有找到i结点,或者说链表就没有i那么多个结点。
if(!p)
return 0;
//如果p没到末尾,此时的j正好是i。直接把p这个结点的内容返回交差。
else
return p->data;
}
//删除第i个结点。
void LinkList::Delete(int i) {
//游标p从头开始
Node *p = first;
//结点指针s用来指向待删除的结点。
Node *s;
//索引j从0开始
int j = 0;
//将游标p后移,直至待删除的结点的前一个结点。
while(p && j < i - 1)
{
p = p->next;
j++;
}
//如果循环结束时,p已经到了末尾,或者p的下一个结点到了末尾(也就是p指向了最后一个有意义的结点)。
//这里解释一下。
//(1)出现p到末尾的情况是:待删除结点的索引i - length(链表) > 1
//此时,p到了末尾,仍然无法达到待删除结点的前一个结点的位置。
//(2)出现p到了最后一个有意义结点的情况是:i - length(链表) == 1
//此时,p到了最后一个有意义的结点,但是后面再没有可删除的i结点了。悲剧。
//这两种情况都是无法删除的,位置不正确。
if(!p || !p->next)
{
cout << "位置不正确" << endl;
}
//如果找到了待删除结点i的前一个位置。
else
{
//补全代码,完成结点i删除的操作。
//那就用s记录下要删除的结点
//然后将i前一个结点直接越过s,连接到s的下一个结点。
//输出该删除结点的数据
//注销该结点。
//----------------------------------------------------
}
}
//求链表的长度,也就是链表结点的个数。
int LinkList::Length() {
//首先,将游标p指向有意义的第一个结点
Node *p = first->next;
//len记录长度
int len = 0;
//只要p没到链表末尾
while(p)
{
//补全代码,完成长度的计算。
//就将p后移
//长度加一
//-------------------------------------------
}
//返回长度
return len;
}
//打印链表的数据。
void LinkList::PrintList() {
//首先,将游标p指向有意义的第一个结点
Node *p = first->next;
//只要p没到链表末尾
while(p)
{
//就输出该结点数据
cout << p->data << endl;
//将p后移
p = p->next;
}
}
//析构函数。
LinkList::~LinkList() {
//游标p从头开始
Node *p = first;
//结点指针s用来指向待删除的结点。
Node *s;
//只要p没到链表末尾
while(p)
{
//补全代码,完成结点的删除操作
//s标记好待删除结点
//p后移到下一个待删除结点
//注销s结点
//------------------------------------------------
}
}
//main函数展现链表应用
int main() {
//定义一个链表工具类对象ll
LinkList ll;
//操作选项option
char option;
//m为插入结点的个数,x用途很多,主要表达结点的数据值,i,j基本上表示索引值
int m, i, x, j;
while(option != 'E')
{
// cout << "请选择不同的链表操作" << endl << "(E:退出;I:插入;S:查找;G:获取结点数据;" << endl;
// cout << "D:删除;L:求长度;V:显示结点信息。)" << endl;
//输入选择
cin >> option;
if(option == 'I')
{
//输入要插入的结点数量
// cout << "输入要插入的结点数量:";
cin >> m;
//依次输入要插入的位置及结点的数据
for(j = 0; j < m; j++)
{
// cout << "第" << j + 1 << "个结点" << endl;
// cout << "请输入结点插入位置:";
cin >> i;
// cout << "请输入结点数据:";
cin >> x;
//插入结点
ll.Insert(i, x);
}
// cout << "插入结束" << endl << endl;
}
//选择S,查询结点
if(option == 'S')
{
// cout << "请输入要查询的数据:";
//输入查询的数据x
cin >> x;
//开始查询
int result;
result = ll.Search(x);
//如果未找到,输出None
if(result == 0)
cout << "None" << endl;
//如果找到了,输出结点的索引值
else
{
cout << "您查找的数据为:" << x << "的结点是第" << result << "个结点" << endl;
}
}
//选择G,获取结点的数据
if(option == 'G')
{
// cout << "请输入要获取的结点索引位置:";
//输入索引位置
cin >> i;
int result;
//获取结点数据
result = ll.Get(i);
//未找到的提示
if(result == 0)
cout << "位置不正确" << endl;
else
//找到就显示结点数据
cout << "第" << i << "个结点的数据为:" << result << endl;
}
//选择D,删除结点
if(option == 'D')
{
// cout << "选择删除结点的索引位置:" << endl;
cin >> i;
//删除结点
ll.Delete(i);
// cout << "删除结束" << endl << endl;
}
//选择L,求链表长度
if(option == 'L')
{
cout << "链表长度为:" << ll.Length() << endl;
}
//选择V,显示所有链表结点数据
if(option == 'V')
{
// 显示链表结点数据。
// cout << "链表结点数据如下:" << endl;
ll.PrintList();
// cout << "显示完毕" << endl << endl;
}
}
return 0;
}
//测试输入:
//I
//3
//1 1
//1 2
//1 3
//D
//2
//S
//3
//S
//2
//G
//2
//L
//V
//E
//预期输出:
//删除结点的数据为:2
//您查找的数据为:3的结点是第1个结点
//None
//第2个结点的数据为:1
//链表长度为:2
//3
//1
代码三:
//编写一个程序,补全代码,利用链表实现栈类,并验证栈的存储和操作。
#include <iostream>
using namespace std;
//----------链表工具类的普适形式,它可以处理以链表为基本支撑结构的数据结构问题,如栈,队列,图等。-----------------
//结点结构
struct Node {
int data; //这个整型变量代表结点携带的数据
Node *next; //指向下一个结点的链表指针(保存着下一个结点的地址)
};
//定义一个处理链表的类
//该类像一个工具包,里面放着各种处理链表的工具,以及链表的数据。
class LinkList {
public:
//构造函数对链表的结构进行初始化,利用new,构建第一个结点。
LinkList() {
//补全代码,完成对头结点的初始化工作。
//新建一个结点(在堆内存中申请一个结点的空间,并将地址返回给first指针,该结点本身是空结点,仅做头结点用)
//将该结点的next指针清空(可以理解为封口,堵头儿,将来遍历的时候,有个到此为止的标记)
//------------------------------------------------
}
//析构函数。
~LinkList();
//插入一个新结点,该结点携带数据x,插入后成为该链表的第i个结点。
void Insert(int i,int x);
//插入一个新结点,该结点携带数据x,插入后成为该链表的第i+1个结点。
void Insert_behind(int i, int x);
//头插法,插入一个新结点,插入后,在头部。也就是第一个结点。
void Insert_head(int x);
//搜索结点,搜索携带数据为x的结点,返回该结点所在的索引号(该结点是第几个结点),未找到则返回0
int Search(int x);
//获取第i个结点的数据,如果未找到,则返回0。
int Get(int i);
//删除第i个结点。
void Delete(int i);
//求链表的长度,也就是链表结点的个数。
int Length();
//打印链表的数据。
void PrintList();
private:
//链表头结点指针,也就是第一个结点的地址。
Node *first;
};
//插入一个新结点,该结点携带数据x,插入后成为该链表的第i个结点。
void LinkList::Insert(int i, int x) {
//结点指针p作为游标指针,从头开始遍历链表,找到要插入的位置。
Node *p;
//结点指针s为新结点指针,通过new构建新结点,插入到链表的正确位置。
Node *s;
//用来计算遍历的位置,直至i的前一个位置为止。
int j;
//插入算法开始:
//首先,讲游标指针p指向头结点。(first为本类唯一的一个属性,就是头结点的地址)
p = first;
//遍历位置游标j从0开始。
j = 0;
//当游标p有意义(也就是指向了一个存在的结点,不为空),
//并且位置游标j没到第i个
while(p && j < i - 1) {
//就继续向后寻找,遍历。
p = p->next;
//位置游标j也向后增加
j++;
//直到p为空(也就是到了链表末尾)或者j已挪动到预定位置i的前一个位置为止。
}
//此时,退出上述while循环,有两种可能:
//(1)p到末尾;
//(2)j到达预定位置,即i的前一个位置。
//如果此时p到末尾,或者i位置是个不合理位置。那报错。
if(!p || i < 1)
{
cout << "位置不正确" << endl;
}
//如果此时p没到末尾,则必定到达了预定位置(i-1)。
//所以,可以生成新结点s,并将结点连接到原来i的位置,也就是现在的p->next的位置
//并将p的next指针指向s,完成插入操作。
//注意,一定是先将新结点尾部挂接在原链表上,再拆开原链表,将前一部分挂接在
//新结点上,组成一个新链表。
else
{
//补全代码,完成新结点的产生和插入操作。
//产生新结点,并填上数据x
//新结点尾部指向当前位置的后方,完成挂接。
//以当前位置为分界,原链表拆开,前一部分尾部挂接在新结点上,组成新链表。
//------------------------------------------------------------
}
}
void LinkList::Insert_behind(int i, int x){
//结点指针p作为游标指针,从头开始遍历链表,找到要插入的位置。
Node *p;
//结点指针s为新结点指针,通过new构建新结点,插入到链表的正确位置。
Node *s;
//用来计算遍历的位置,直至i的前一个位置为止。
int j;
//插入算法开始:
//首先,讲游标指针p指向头结点。(first为本类唯一的一个属性,就是头结点的地址)
p = first;
//遍历位置游标j从0开始。
j = 0;
//当游标p有意义(也就是指向了一个存在的结点,不为空),
//并且位置游标j没到第i个
while(p && j < i) {
//就继续向后寻找,遍历。
p = p->next;
//位置游标j也向后增加
j++;
//直到p为空(也就是到了链表末尾)或者j已挪动到预定位置i的前一个位置为止。
}
//此时,退出上述while循环,有两种可能:
//(1)p到末尾;
//(2)j到达预定位置,即i的前一个位置。
//如果此时p到末尾,或者i位置是个不合理位置。那报错。
if(!p || i < 0)
{
cout << "位置不正确" << endl;
}
//如果此时p没到末尾,则必定到达了预定位置(i-1)。
//所以,可以生成新结点s,并将结点连接到原来i的位置,也就是现在的p->next的位置
//并将p的next指针指向s,完成插入操作。
//注意,一定是先将新结点尾部挂接在原链表上,再拆开原链表,将前一部分挂接在
//新结点上,组成一个新链表。
else
{
//补全代码,完成新结点的产生和插入操作。
//产生新结点,并填上数据x
//新结点尾部指向当前位置的后方,完成挂接。
//以当前位置为分界,原链表拆开,前一部分尾部挂接在新结点上,组成新链表。
//------------------------------------------------------------
}
}
//头插法,插入一个新结点,插入后,在头部。也就是第一个结点。
void LinkList::Insert_head(int x){
//补全代码,利用Insert_behind方法或Insert方法,实现在头部插入新结点的功能
//-------------------------------------------------------------------
}
//搜索结点,搜索携带数据为x的结点,返回该结点所在的索引号(该结点是第几个结点)
//未找到则返回0
int LinkList::Search(int x) {
//结点指针p作为游标指针,从头开始遍历链表
Node *p;
//j记录结点的索引位置
int j;
//算法开始:
//首先,将p指向有意义的第一个结点(也就是索引为1的结点,也是实际的第二个结点)
p = first->next;
//j记录为1(从0开始的)
j = 1;
//只要p未到末尾
while(p)
{
//补全代码,完成值为x的结点的查找
//考查游标p指向的结点,如果该结点恰好携带数据x,则退出循环,找到了。
//如果该结点数据并不是x,则p继续向后遍历下一个结点继续考查
//------------------------------------------------------
//索引值也随之后移。
j++;
}
//如果上述循环正常退出,则p到末尾,也就是没找到
if(!p)
//则返回0,表示未找到。有效的索引值从1开始。
return 0;
//如果上述循环没正常退出,也就是break被激活,那定然是找到了x结点。
else
//则将当时记录的索引j返回。交差成功。
return j;
}
//获取第i个结点的数据,如果未找到,则返回0。
int LinkList::Get(int i) {
//首先,将游标p指向有意义的第一个结点(也就是索引为1的结点,也是实际的第二个结点)
Node *p = first->next;
//j记录为1(从0开始的)
int j = 1;
//补全代码,实现结点的获取。
//向后移动游标,直至i结点(也就是j==i时,退出,如果此时的p仍然有意义的话)
//提示,游标p后移同时,索引j也应后移。
//-------------------------------------------------------------
//如果p到末尾退出的,那证明没有找到i结点,或者说链表就没有i那么多个结点。
if(!p)
throw 0;
//如果p没到末尾,此时的j正好是i。直接把p这个结点的内容返回交差。
else
return p->data;
}
//删除第i个结点。
void LinkList::Delete(int i) {
//游标p从头开始
Node *p = first;
//结点指针s用来指向待删除的结点。
Node *s;
//索引j从0开始
int j = 0;
//将游标p后移,直至待删除的结点的前一个结点。
while(p && j < i - 1)
{
p = p->next;
j++;
}
//如果循环结束时,p已经到了末尾,或者p的下一个结点到了末尾(也就是p指向了最后一个有意义的结点)。
//这里解释一下。
//(1)出现p到末尾的情况是:待删除结点的索引i - length(链表) > 1
//此时,p到了末尾,仍然无法达到待删除结点的前一个结点的位置。
//(2)出现p到了最后一个有意义结点的情况是:i - length(链表) == 1
//此时,p到了最后一个有意义的结点,但是后面再没有可删除的i结点了。悲剧。
//这两种情况都是无法删除的,位置不正确。
if(!p || !p->next)
{
cout << "位置不正确" << endl;
}
//如果找到了待删除结点i的前一个位置。
else
{
//补全代码,完成结点i删除的操作。
//那就用s记录下要删除的结点
//然后将i前一个结点直接越过s,连接到s的下一个结点。
//输出该删除结点的数据
//注销该结点。
//----------------------------------------------------
}
}
//求链表的长度,也就是链表结点的个数。
int LinkList::Length() {
//首先,将游标p指向有意义的第一个结点
Node *p = first->next;
//len记录长度
int len = 0;
//只要p没到链表末尾
while(p)
{
//补全代码,完成长度的计算。
//就将p后移
//长度加一
//-------------------------------------------
}
//返回长度
return len;
}
//打印链表的数据。
void LinkList::PrintList() {
//首先,将游标p指向有意义的第一个结点
Node *p = first->next;
if(!p){
// cout << "链表无结点" << endl;
}
else{
//只要p没到链表末尾
while(p)
{
//就输出该结点数据
cout << p->data << endl;
//将p后移
p = p->next;
}
}
}
//析构函数。
LinkList::~LinkList() {
//游标p从头开始
Node *p = first;
//结点指针s用来指向待删除的结点。
Node *s;
//只要p没到链表末尾
while(p)
{
//补全代码,完成结点的删除操作
//s标记好待删除结点
//p后移到下一个待删除结点
//注销s结点
//------------------------------------------------
}
}
//---------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int main(){
//-------------链表形式的栈操作验证--------------------------
//利用基础链表类进行栈操作验证
//建立栈
LinkList l;
int i;
//压栈的次数
int num;
//压栈的数据
int x;
//输入压栈次数
cin >> num;
//依次压栈x
for(int i = 0; i < num; i++){
cin >> x;
l.Insert_head(x);
}
//查看数据
l.PrintList();
//查看栈长度
cout << l.Length() << endl;
//出栈操作
for(i = 0; i < 2; i++){
//出栈操作
try{
//补全代码
int data;
//利用Get方法弹出栈顶结点,保存至data,并输出
//再利用Delete方法注销被弹出的栈顶结点
//------------------------------------------------------------
}
catch(int){
cout << "栈空" << endl;
}
}
//查看数据
l.PrintList();
//查看栈长度
cout << l.Length() << endl;
return 0;
}
//测试输入:
//3
//1
//2
//3
//预期输出:
//3
//2
//1
//3
//出栈弹出数据:3
//出栈弹出数据:2
//1
//1
//测试输入:
//1
//1
//预期输出:
//1
//1
//出栈弹出数据:1
//栈空
//0