第一章 绪论(4)

来源:网络收集 时间:2025-07-09 下载这篇文档 手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xuecool-com或QQ:370150219 处理(尽可能给您提供完整文档),感谢您的支持与谅解。点击这里给我发消息

否则,先“迈一步”到达(g,h)点,而后再进行递归调用:solve(g, h, k+1, ok);以实现从新点(g,h)出发,将k+1直到25这些“棋子”(数码)分别摆放到棋盘上,若成功则通过引用参数ok返回true(否则返回false)。 点评:

(1)也可编制第二种解法的主函数:将棋盘上的n平方个点依次作为巡游起点的初始坐标位置(x1,y1),判断从每一位置出发是否有解或无解(输出“OK!”或“NO!”,但并不输出“路线图”)。 (2)若更改程序中的n值(如改为4或6等),便可求解其他阶数的巡游“路线图”。

(3)可改用非递归方法设计并编写solve函数,那样的话,通常要增加一个记录摆放“棋子”信息的数组,可记录下是沿着什么方向到达了当前的什么位置(在那儿摆放了“棋子”)等,而且对上述数组可按照栈(stack)的方式来使用(栈总是采用FILO即所谓的先进后出使用方式),以便在“无路可走”的情况下,回退(回溯)到上一个位置,接着按照另外的方向去寻找其他的“行走”方法。

32. 编写程序对八皇后问题进行求解:在8行8列的棋盘上放置8个皇后,使任一个皇后都不能吃掉其他的7个皇后(注:皇后可吃掉与她处于同行或同列或同一对角线上的其他棋子),并将结果以某种方式显示出来。

例如,当求出下述的一个解时,可输出如下信息来表示该解(输出了表示摆放皇后的坐标位置以及“棋盘状态”— 棋盘中有皇后的位置放一个“Q”字符,其他位置为“+”字符)。 (1,1) (5,2) (8,3) (6,4) (3,5) (7,6) (2,7) (4,8) Q + + + + + + + + + + + + + Q + + + + + Q + + + + + + + + + + Q + Q + + + + + + + + + Q + + + + + + + + + Q + + + + Q + + + + + 提示:

(1) 通过“int LineNum[9]; bool a[9], b[15], c[15];”说明具有全局作用域的4个数组。其中的: LineNum[i]表示第i列的皇后要放的行位置(只用其中的列号1到8); a[i]为true(i =1,2,…,8)表示第i行上尚未放皇后;

b[i]为true(i =0,1,2,…,14)表示第i条斜对角线上尚未放皇后(斜对角线指的是“/”状对角线,该对角线上各点的行列号之和i+j为一个常数);

c[i]为true(i=0,1,2,…,14)表示第i条反斜对角线上尚未放皇后(反斜对角线指的是“\\”状对角线,该对角线上各点的行列号之差i-j为一个常数)。

从而当使用语句“if ( a[j] && b[i+j-2] && c[i-j+7] ) LineNum[i]=j;”时,可用于判断并实现:如果在第j行的第i列上放置皇后安全的话,则将一枚皇后放置到那儿。

(2)编制一个具有如下原型的递归函数solve,它负责往第i列开始的连续8-i+1列上均放上皇后,若成功则通过引用参数ok返回true(否则返回false)。 void solve(int i, bool& ok);

摆放皇后之后,若i=8即已放满时则递归出口;否则通过solve(i+1,ok);进行递归调用。 (3)编制主函数,首先初始化一个“空棋盘”,即将a、b、c数组的各元素均置为true(表示当前棋盘的8个行、15条斜对角线以及15条反斜对角线上都尚未摆放皇后)。而后执行调用语句“solve(1, ok);”,它负责往第1列开始的连续8列上均放上皇后,若成功则通过引用参数ok返回true(否则返回false)。

点评:

(1)可改用非递归方法设计并编写solve函数,那样的话,通常要设置数组来记录皇后的摆放位置信息,还要记录这些皇后所产生的“影响面”(所建立的“势力范围”)— 使得哪些行列位置不可再摆放皇后。当在新的行列位置摆放了皇后、但此时又无法进一步摆放其他的皇后时,要回退(回溯)到上一个位置接着去考虑另外的“行走”方法(若还有的话)等等。但注意,“回退”一步后,要同时“撤销”由于该步的回退而关联的那些“影响面”(释放“势力范围”)。

(2)本程序只是找到了某一种“摆放方案”而终止,还可进一步考虑寻找其他各种不同的“摆放方案”(实际上共有92种)。

(3)也可用同样的方法去处理其他“阶数”的皇后问题,如求解四皇后问题等。

第六章 指针,引用与动态内存分配

思 考 题

1. 什么是地址,什么是地址中的内容,两者的区别是什么?

2. 运算符“&”和“*”各有几种用法?各自的使用方式以及使用含义是什么? 3. 什么是指针?地址和指针有什么样的关系? 4. 如下3处出现的*pi的使用含义有什么不相同吗? int i=23, *pi=&i; cout<<*pi; *pi=56;

5. 指针的值和类型是怎样规定的?指针的值与其他类型变量的值是否有区别?

6. 假设程序中有“int a[20];int *pa=a;”的说明,要表示数组元素a[i]时(0≤i≤19),有几种方法可以使用呢?

7. 指针可以进行哪些运算?和普通数据类型的运算有什么不同?

8. 假设程序中有“int a[10],b[10][10];”的说明,请问数组名a以及b[i]都与地址及指针有某些关系吗(0≤i≤9)?a[i]与b[i]的使用含义相同吗?a+1与b+1的含义有什么不同?a[2]+1与b[2]+1的使用含义相同吗?

9. 下面按9种不同方式所定义的p有什么区别与联系?如何对每一种p进行使用? int p; int *p; int **p;

int p[10]; int *p[10]; int (*p)[10]; int p(); int *p(); int(*p)();

10. 在“2.4.1 主函数”一节中,给出过带参数的main函数的如下一般使用格式: void main(int argc, char * argv[]){…} 你能细致地描述参数argv所表达的数据结构吗?

11. 试述指针在函数的参数传递中的作用及其使用方法。指针参数与数组参数是否有某种形式的关联?

12. 怎样使用动态分配运算符new来生成无名的动态变量以及无名的动态数组?如何对这种动态变量及动态数组进行使用?如何使用delete来配合new释放上述的动态存储空间? 13. 什么是引用?引用和指针的区别是什么?引用型参数具有哪些优点? 14. 引用型的函数返回值与非引用型的函数返回值是否有某些不相同?

15. 如何定义结构类型?如何说明与使用结构变量及其分量?结构与数组的定义与使用有哪些异同?

16. 假设某结构的分量中含有指向本结构的指针(如下面的person结构类型),请问如何通过使用new及某些相关步骤来生成一个链表呢? struct person {

...

person * next; };

17. 在上一题person结构类型的基础上,如下的程序“构架”是否可以用来实现生成一个具有n个项的链表(而总将新链表项加入到当前已有链表的末尾)? person *head, *tail, *temp;//head指向链表首项,tail指向末项 tail = head = NULL; //使head及tail均指向“空”,表示空链表 for(i=0; i

temp=new person; //生成一个person型的动态新表项

temp->next=NULL; //新表项将充当链表末项,将其next域置为NULL

... //如,通过cin输入(*temp)结构(变量)的其它各分量之值等 if(head==NULL) head=tail=temp; //链表为空时,新表项既为首项又为末项 else { //链表非空时

tail->next=temp; //新表项加入到原链表的末项之后 tail=temp; //新表项成为链表的新末项 }

} //i循环体结束

18. 在C++语言中使用指针有哪些优点?指针在程序安全方面是否会有负面影响?

练 习 题

1. 读程序写结果。程序中使用了与指针相关的常用运算:取内容运算*,取地址运算&,指针加减一个常数(结果仍为指针),两个指针进行比较等。 #include void main(void) { int a[10]={10,11,12}; int *p=a, *q=&a[9];

*(p+3)=13; *(q-5)=*(p+3)+1; for (int i=5; i<10; i++) *(p+i)=80+i;

cout<<\ cout<<\ for (i=3; i<8; i++) cout<<*(a+i)<<\ \ cout<<\ cout<<\ while (q>&a[4]) cout<<*q--<<\ \

cout<<\}

2. 读程序,写出运行结果。注意其中通过指针参数实现了主调函数与被调函数间的“双向传值”。 #include

void split(double x, int *iPart, double *fPart) { *iPart=int(x); *fPart=x-*iPart; }

double f(double *a, int n) { int i, intPt;

double fracPt, maxfracPt=0; for(i=0; i

split( *(a+i), &intPt, &fracPt ); if( fracPt>maxfracPt) maxfracPt=fracPt; *(a+i)=intPt; }

return maxfracPt; }

void main() { int i;

double maxfr, a[6]={1.1, 2.2, 3.3, 9.9, 6.6, 5.0}; maxfr=f(a, 6);

cout<<\ for(i=0; i<6; i++) cout<

提示:函数split负责“分离”出x的整数部分与小数部分,分别放于*iPart与*fPart处,由于形参iPart与fPart都是指针,从而可实现“双向传值”而将这两个结果同时“带回去”。函数f负责从指针a为首地址的位置开始,对最前面的n个double型数进行处理:通过调用split改变数组各元素值(只要整数部分),并返回“分离”后之小数部分的大者。

点评:当被调函数的形参是指针,而又在该被调函数中更改此形参指针所指向的变量值的话,就意味着是更改主调函数中相应实参指针所指向的变量值,从而可实现所谓的“双向传值”。 3. 读程序写结果。注意,并非只要使用指针参数就必然能实现“双向传值”。 #include #include void f1(int* p, int* q) { p=new int; *p=66; *q=66;

cout<<\}

void f2(char* s) {

cout<<\ char a[20]=\ s=a;

cout<<\}

void main() { int a=2, b=5; f1(&a, &b);

cout<<\ char e[10]=\

cout<<\ f2(e);

cout<<\}

点评:被调函数f1中,通过“p=new int;”改变了形参指针p的值,使它指向了另外的位置,从而使随后的“*p=66;”无法实现“双向传值”!而被调函数f2中通过“s=a;”改变了形参指针的值,使它指向了另外的位置,这样也不可实现“双向传值”!注意,只有在被调函数中改变形参指针所指变量的值(那时改变的将是主调函数中实参指针所指变量的值),才能真正实现“双向传值”。 4. 假设在main函数中有如下的说明(数组a中存放了n个字符串,即名字): const int n=10;

char a[n][31] = {\ \ \ \ \ \ \da\ \ \编制具有如下原型的自定义函数:

int search(char (*p)[31], int n, char* name);

负责在字符串数组p的前n个字符串(名字)中,查找给定串name的出现位置(下标值)并返回,若p中不出现name的话,返回-1。

并编制主函数,输入要查找的某个名字(字符串)name,而后通过如下形式的语句对上述函数进行调用,之后输出相关结果(出现位置,即下标值): int idx = search(a, n, name);

//从a数组的第一个名字(0下标,第1行)开始查找 int idx = search(a+3, n, name);

//从a数组的第四个名字(3下标,第4行)开始查找

提示:函数search的第一个参数p为指向一维数组的指针,按照“char (*p)[31]”所说明的p实际上可看作是一个二维字符数组,即是说,p[i]即*(p+i)为一个一维字符数组(字符串,至多可存放31个字符);要查找给定串name在p中的出现位置(下标值),可使用如下形式的if语句来实现“if( strcmp(p[i], name) == 0 ) return (i);。”

点评:若将形参说明“char (*p)[31]”修改为“char p[][31]”,而且其他一切都不必修改,同样可实现本题所给出的求解任务,从而可体会到指向一维数组的指针形参p与二维形参数组p的密切关系。

若将a数组中的名字(字符串)按照“字典序”进行了升序排列的话,search函数中除可使用顺序查找方式之外,还可按照折半法(二分法)来进行查找。

5. 编制具有如下原型的函数FindPlace,该函数返回字符串str中第一次出现字符c的位置(地址值,即指向字符c的指针)。如果没有c字符则返回空指针NULL。并编制主函数对它进行调用以验证其正确性。

char * FindPlace(char *str,char c);

注意:若返回的字符指针值为p的话,那么,通过“cout<

思考:若寻找并返回c字符在字符串str中最后一次出现的位置的话,实现方式与此类似。 6. 编制具有如下原型的函数findFirst以及 findLast,而后编制主函数,任意输入两个字符串,将它们用作实参来调用这两个函数,以验证其正确性。 char * findFirst(char * sourceStr, char * subStr); char * findLast(char * sourceStr, char * subStr);

findFirst函数的功能为:返回源串sourceStr中第一次出现subStr子字符串的头字符位置(地

百度搜索“70edu”或“70教育网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,70教育网,提供经典综合文库第一章 绪论(4)在线全文阅读。

第一章 绪论(4).doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印 下载失败或者文档不完整,请联系客服人员解决!
本文链接:https://www.70edu.com/wenku/401026.html(转载请注明文章来源)
Copyright © 2020-2025 70教育网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:370150219 邮箱:370150219@qq.com
苏ICP备16052595号-17
Top
× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:7 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219