实验2.1线性表的应用(最小差值)
分别提交两个附件:
1:设计文档(提交PDF格式的文件,文件名要规范,参看规范)。
2:实验源码包。(文件名也要规范,可以参考报告文件的格式)
实验2.1实验报告
一、问题分析
要处理的对象:n个正整数
要实现的功能:找出这组整数之中相差最小的两个数
结果显示:输出相差最小的两个数的差值
二、算法思想设计
① 先用一个整型变量n存储此组正整数的个数,n同时也为储线性表的储存空间
② 将n个正整数依次储存到线性表中
③ 先让线性表中的第1个数依次和后续的数字做差取绝对值,用一个变量answer存储每一次做差后差值的最小值
④ 再让线性表中第2个数依次和后续的数字做差取绝对值,answer记录最小差值。一直做差比较更新差值answer,知道让线性表倒数第二个数和后续数字做完比较并做好差值记录为止。
⑤ 此时的answer的值即为差值的最小值
三、样例分析
【样例一】5
1 5 4 8 20
【分析】
① n=5,线性表长度为5,储存数字依次为1,5,4,8,20
② 线性表中第一个数字1分别和后续数字做差值
abs(1-5)=4,answer=4;
abs(1-4)=3,3<4,answer=3;
abs(1-8)=7,7>3,answer=3;
abs(1-20)=19,19>3,answer=3;
③ 线性表中第二个数字5分别和后续数字做差值
abs(5-4)=1,1<3,answer=1;
abs(5-8)=3,3>1,answer=1;
abs(5-20)=15,15>1,answer=1;
④ 线性表中第三个数字4分别和后续数字做差值
abs(4-8)=4,4>1,answer=1;
abs(4-20)=16,16>1,answer=1;
⑤ 线性表中第三个数字4分别和后续数字做差值
abs(8-20)=12,12>1,answer=1;
【样例输出】此时answer=1 ,故输出1
【样例二】5
9 3 6 1 3
【分析】
1)n=5,线性表长度为5,储存数字依次为1,5,4,8,20
2)线性表中第一个数字9分别和后续数字做差值
abs(9-3)=6,answer=6;
abs(9-6)=3,3<6,answer=3;
abs(9-1)=8,8>3,answer=3;
abs(9-3)=6,6>3,answer=3;
3)线性表中第二个数字3分别和后续数字做差值
abs(3-6)=3,3=3,answer=1;
abs(3-1)=2,2<3,answer=2;
abs(3-3)=0,0<2,answer=0;
4)线性表中第三个数字6分别和后续数字做差值
abs(6-1)=5,5>0,answer=0;
abs(6-3)=3,3>0,answer=0;
5)线性表中第四个数字1分别和后续数字做差值
abs(1-3)=2,2>0,answer=0;
【样例输出】此时answer=0 ,故输出0
四、关键功能的算法步骤
① 让线性表的指针指向头结点Line.moveToStart();
② 采用for循环n次,每次读取一个整数trans,通过Line.append(trans)将n个整数放入线性表
③ 整型变量x未线性表第i个数字,通过Line.moveToPos(i),x=Line.getValue()实现x的取值,变量y依次为第i+1到第n个数字,通过Line.moveToPos(j),x=Line.getValue()实现y的取值。变量y每往后移一个数字,和x做一次差值,将较小的差值存储在answer变量中。经过(n-i-1)次的比较,对于第i个数字对应的answer的最小值。
④ 通过i从第1个数遍历到第n-1个数,实现此组数据两两之间的比较,此时answer为线性表任意两个数字差值的最小值。
五、分析
1)for(int i = 0 ; i < n ; i++) {cin >> trans;Line.append(trans);},在线性表中依次存储数据,时间复杂度为n;
2)在实现两两数字比较的过程中采用for(int i = 0 ; i < n-1 ; i++) {for(int j = i+1 ; j < n ; j++)}的双重for循环,时间复杂度为/2;
3)总共的时间复杂度为O()
4)计算过程中只开辟了单个的整型变量储存数据,故空间复杂度为O(1)
六、ADT的实现
① void clear(),输入为空,无返回值,功能是删除原有数组,将线性表的长度设为0
② void insert(const E& it),输入为需要插入的数据的值,无返回值,功能是在当前位置插入一个值为it的数据
③ void append(const E& it),输入为需要插入的数据的值,无返回值,功能是在顺序表的末尾追加一个值为it的数据
④ E remove(),无输入,返回值是类型为E的一个数据,功能是删除并返回当前元素
⑤ void moveToStart(),将curr当前位置设置为开头,无输入输出值,将当前位置移动到头结点处
⑥ void moveToEnd(),将curr当前位置设置为末尾,无输入输出值,将当前位置移动到尾结点处
⑦ void prev(),将curr当前位置向前移动一位,若为头结点则不移动,无输入输出值
⑧ void next(),将curr当前位置向后移动一位,若为尾结点则不移动,无输入输出值
⑨ int length() const,无输入值,输出值为一个整型值,功能是返回线性表的长度
⑩ int currPos() const,无输入值,输出值为一个整型值,功能是返回线性表当前位置的值
⑪ void moveToPos(int pos),输入值为一个不超过线性表位置范围的整数值,无输出值,功能是将curr当前位置移动到pos位置
⑫ const E& getValue() const,无输入值,输出值是一个类型为E的数据,功能是返回当前位置的元素值
实验2.2线性表的应用(游戏)
分别提交两个附件:
1:设计文档(提交PDF格式的文件,文件名要规范,参看规范)。
2:实验源码包。(文件名也要规范,可以参考报告文件的格式)。
代码实现部分:
AList.h
#ifndef ALIST_H
#define ALIST_H
#include "list.h"
#include <assert.h>
template<typename E> // Array-based list implementation 基于数组的线性表实现
class AList : public List<E> {
private:
int maxSize; // Maximum size of list 顺序表的容量
int listSize; // Number of list items now 目前的大小
int curr; // Position of current element 当前元素的位置
E* listArray; // Array holding list elements 列表元素将存放到该数组中
public:
AList(int size=100) { // Constructor 构造函数
maxSize = size;
listSize = curr = 0;
listArray = new E[maxSize];
}
~AList() { delete [] listArray; } // Destructor 析构函数
void clear() { // Reinitialize the list 初始化顺序表
delete [] listArray; // Remove the array 删除原有数组
listSize = curr = 0; // Reset the size 重新设置列表参数
listArray = new E[maxSize]; // Recreate array 新建空数组
}
// Insert "it" atcurrent position 在当前位置插入it
void insert(const E& it) {
assert(listSize < maxSize); //"List capacity exceeded"超出顺序表范围会断言终止程序
for(int i=listSize; i>curr; i--) // Shift elements up 右移元素
listArray[i] = listArray[i-1]; // to make room
listArray[curr] = it;
listSize++; //Increment list size 列表长度加一
}
void append(const E& it) { // Append "it" 在顺序表的末尾追加it
assert(listSize < maxSize); // 断言判断
listArray[listSize++] = it;
}
// Remove and return thecurrent element. 删除并返回当前元素
E remove() {
assert((curr>=0) && (curr <listSize)); // No element 没有元素会断言终止程序
E it = listArray[curr]; // Copy the element 拷贝当前元素
for(int i=curr; i<listSize-1; i++) // Shift them down 左移元素
//listArray[curr]将被覆盖掉
listArray[i] = listArray[i+1];
listSize--; // Decrementsize 列表长度减一
return it;
}
void moveToStart() { curr = 0; } // Reset position. 将curr当前位置设置为开头
void moveToEnd() { curr = listSize; } // Set at end . 将curr设置为末尾
void prev() { if (curr != 0) curr--; } // Back up. 将curr前移一位
void next() { if (curr < listSize) curr++;} // Next. 将curr后移一位
// Return list size 返回顺序表长度
int length() const { return listSize; }
// Return current position 返回当前位置
int currPos() const { return curr; }
// Set current list position to "pos" 将当前位置curr设置为pos
void moveToPos(int pos) {
assert ((pos>=0)&&(pos<=listSize)); // Pos out of range
//pos超出顺序表范围会断言终止程序
curr = pos;
}
const E& getValue() const { // Returncurrent element 返回值是当前元素
assert((curr>=0)&&(curr<listSize)); //No current element
//当前位置超出范围时断言终止程序
return listArray[curr];
}
};
#endif
list.h
#ifndef LIST_H
#define LIST_H
template<typename E> class List { // List ADT 抽象数据类型定义
private:
void operator =(const List&) {} // Protect assignment
List(const List&) {} // Protect copy constructor
public:
List() {} // Default constructor 构造函数
virtual ~List() {} // Basedestructor 析构函数
// Clear contents from thelist, to make it empty. 清空列表中的内容
virtual void clear() = 0;
// Insert an element at the current location.
// item: The element to be inserted 在当前位置插入元素item
virtual void insert(const E& item) = 0;
// Append an element at the end of the list.
// item: The element to be appended 在表尾添加元素item
virtual void append(const E& item) = 0;
// Remove and return the current element.
// Return: the element that was removed. 删除当前元素,并将其作为返回值
virtual E remove() = 0;
// Set the current position to the start of the list. 将当前位置设置为顺序表起始处
virtual void moveToStart() = 0;
// Set the current position to the end of the list. 将当前位置设置为顺序表末尾
virtual void moveToEnd() = 0;
// Move the current position one step left. No change
// if already at beginning. 将当前位置左移一步,如果当前位置在首位就不变
virtual void prev() = 0;
// Move the current position one step right. No change
// if already at end. 将当前位置右移一步,如果当前位置在末尾就不变
virtual void next() = 0;
// Return: The number of elements in the list. 返回列表当前的元素个数
virtual int length() const = 0;
// Return: The position of the current element. 返回当前元素的位置
virtual int currPos() const = 0;
// Set current position.
// pos: The position to make current. 将当前位置设置为pos
virtual void moveToPos(int pos) = 0;
// Return: The current element. 返回当前元素
virtual const E& getValue() const = 0;
};
#endif
main.c
#include <iostream>
#include "list.h"
#include "AList.h"
using namespace std;
int main()
{
int n; int answer = 12345,mid = 12345;
cin >> n;
AList<int> Line(n);
Line.moveToStart();
for(int i = 0 ; i < n ; i++)
{
int trans;
cin >> trans;
Line.append(trans);
}
Line.moveToStart();
for(int i = 0 ; i < n-1 ; i++)
{
for(int j = i+1 ; j < n ; j++)
{
Line.moveToPos(i);
int x = Line.getValue();
Line.moveToPos(j);;
int y = Line.getValue();
mid = x-y;
mid = (mid > 0)? mid:(-mid);
answer = (mid > answer)? answer:mid;
}
}
cout << answer << endl;
return 0;
}
实验2.2实验报告
一、问题分析
【要处理的对象】
n个孩子,报数关键值为k
【要实现的功能】
游戏开始,从1号小朋友开始顺时针报数,接下来每个小朋友的报数是上一个小朋友报的数加1。若一个小朋友报的数为k的倍数或其末位数(即数的个位)为k,则该小朋友被淘汰出局,不再参加以后的报数。当游戏中只剩下一个小朋友时,该小朋友获胜。
【结果显示】
输出一行,包含一个整数,表示获胜的小朋友编号
二、算法思想设计
① 用一个vector容器存储n个孩子的编号,编号依次为1-n
② 从编号1的位置开始迭代计数,遇到计数为n的整数倍或者个位数为k时,将这个迭代器指向的值改为0,代表该孩子已经输掉比赛。迭代器迭代到最后一位之后,再从头开始循环。
③ 每淘汰一个孩子,n个孩子减少一个,直到只剩下一个孩子。
④ 通过对容器内每一个值进行遍历,值不为0的数的位置即为获胜孩子的编码。
三、样例分析
【样例一】5 2
【分析】
当n=5, k=2时:
1号小朋友报数1;
2号小朋友报数2淘汰;
3号小朋友报数3;
4号小朋友报数4淘汰;
5号小朋友报数5;
1号小朋友报数6淘汰;
3号小朋友报数7;
5号小朋友报数8淘汰;
3号小朋友获胜。
【样例输出】3号小朋友获胜,输出3.
【样例二】7 3
【分析】
当n=7, k=3时:
1号小朋友报数1;
2号小朋友报数2;
3号小朋友报数3淘汰;
4号小朋友报数4;
5号小朋友报数5;
6号小朋友报数6淘汰;
7号小朋友报数7;
1号小朋友报数8;
2号小朋友报数9淘汰;
4号小朋友报数10;
5号小朋友报数11;
7号小朋友报数12淘汰;
1号小朋友报数13淘汰;
4号小朋友报数14;
5号小朋友报数15淘汰;
4号小朋友获胜。
【样例输出】4号小朋友获胜,输出4.
四、关键功能的算法步骤
① 让容器中的n个数依次报数,当(people[key] > 0)(即对应的孩子没有被淘汰时),计数num+1;
② 当(num % k == 0 || num% 10 == k)&&(people[key]!=0)(报数为k的倍数或者个位数为k,并且该编码对应的孩子没有被淘汰)时,淘汰这个孩子,孩子个数times-1,people[key] = 0(值为0代表该小孩被淘汰);
③ 循环报数过程,直到人数times ==1
④ 通过迭代器对n个数进行判断,找到不为0的数字的对应编号,即为获胜小孩的编号
五、分析
1)将n个孩子的编号依次放入vector容器中,时间复杂度为n
2)通过while循环实现循环报数,直到找到胜利的孩子,时间复杂度为n
3)遍历容器找到胜利的孩子,时间复杂度为n
4)总的时间复杂度n+n+n=3n,时间复杂度为O(n)
5)计算过程中只开辟了单个的整型变量储存数据,故空间复杂度为O(1)
代码实现部分:
#include
#include
using namespace std;
int main()
{
int n , k;
cin >> n >> k;
vector people;
for(int i = 1 ; i <= n ;i++)
people.push_back(i);
int times = n;int key = 0 ,num=0;
while(times > 1)
{
if(people[key] > 0)
{
num++;
}
if((num % k == 0 || num% 10 == k)&&(people[key]!=0))
{
people[key] = 0;
times–;
}
key++;
key = key%n;
}
for(int i = 0 ; i < n ; i++)
{
if(people[i] != 0)
cout << people[i] << endl;
}
return 0;
}