hnu 数据结构 实验二

实验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;
}

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值