阶段作业1 线性结构 编程题
阶段作业1 线性结构 编程题
[toc]
【作业要求】
(1) 每个编程题均要求提交函数代码、测试代码及测试截图;
(2) 每组提交一份word文档。每个编程题要配备一个讲解视频。本次作业需提交1份word文档+6个讲解视频。如:线性结构作业.word,1.mp4,2.mp4等;
(3) 小组内每名成员至少完成2题,完成哪一题,就相应制作哪一题的讲解视频。
(4) 组长负责制。组长负责组织成员按时、按要求完成作业,负责提交作业。如遇到某个题目没有组员可以完成时,组长负责完成。
【说明】以下编程题可以使用实验课中给出的顺序表、单链表等相关实现文件。
在递增有序的顺序表中添加新接口bool ListInsert_Order(SqList &L, ElemType item)。实现插入新元素并保持有序性不变。说明你的算法的时间复杂度。(15分)
在单链表中添加接口Node * Find(Node *Head, int item),实现在带头结点的单链表Head中查找值为item的结点,查找成功则返回其地址,如果不存在这样的结点,则返回NULL。 (10分)
单链表中添加接口实现删除单链表中所有与指定值相同的结点的功能。(20分)
编写函数,通过一趟遍历,将链表中所有结点的链接方向“原地”逆转,即利用原表的存储空间。说明此算法的空间复杂度。(20分)
编写函数,删除递增有序链表中值大于mink且小于maxk的所有元素(mink和maxk是给定的两个参数,其值可以与表中的元素相同,也可以不同 )。(20分)
假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。(15分)
①下面所示的序列中哪些是合法的?
- IOIIOIOO B. IOOIOIIO C. IIIOIOIO D. IIIOOIOO
②通过对①的分析,写出一个算法,判定所给的操作序列是否合法。若合法,返回true,否则返回false(假定被判定的操作序列已存入一维数组中)。
【第1题】
// NueXini
#include <iostream>
#include <cstdlib>
#include <ctime>
#define MaxSize 100
typedef int ElemType;
typedef struct
{
int length;
ElemType data[MaxSize];
} SqList;
//初始化顺序表
void InitList(SqList *&L)
{
L->length = 0;
}
//输出线性表长度和元素
void ShowList(SqList *&L)
{
std::cout << "表长度:" << L->length << "\n表元素:";
for (int i = 1; i <= L->length; i++)
{
std::cout << L->data[i] << " ";
}
std::cout << std::endl;
}
//在有序表中加入一个数,使得表依然有序
bool InsertList(SqList *&L, ElemType insert)
{
int i, j;
if (L->length == MaxSize)
{
return false;
}
for (i = 0; i < L->length; i++)
{
if (insert >= L->data[i])
{
for (j = L->length; j >= i; j--)
L->data[j + 1] = L->data[j]; // 结点后移
L->data[i] = insert;
L->length++;
return 1;
}
}
L->data[L->length++] = insert;
return true;
}
int main()
{
SqList *L = new SqList();
InitList(L);
ShowList(L);
srand(time(0));
for (size_t i = 0; i < 10; i++)
{
ElemType _a = rand() % 13;
InsertList(L, i + _a);
}
ShowList(L);
return 0;
}
【第2题】
// NueXini
#include <iostream>
typedef int ElemType;
typedef struct NNode
{
ElemType data;
struct NNode *next;
} Node;
void InitList(Node *&L)
{
L->next = NULL;
}
void TraverseList(Node *L)
{
Node *p = L->next;
while (p)
{
std::cout << p->data << " ";
p = p->next;
}
std::cout << std::endl;
}
bool ListInsert(Node *L, int pos, ElemType item)
{
Node *p = L;
int i = 0;
while (p && i != pos - 1)
{
p = p->next;
i++;
}
if (p == NULL)
{
return false;
}
Node *t = new Node;
t->data = item;
t->next = p->next;
p->next = t;
return true;
}
Node *Find(Node *Head, ElemType item)
{
{
Node *p = Head->next;
while (p && p->data != item)
{
p = p->next;
}
return p;
}
}
int main()
{
Node *a = new Node();
InitList(a);
for (size_t i = 0; i < 10; i++)
{
if (!ListInsert(a, i + 1, i))
{
std::cout << "false" << std::endl;
}
}
TraverseList(a);
std::cout << Find(a, 2) << std::endl;
return 0;
}
【第3题】
leetcode: 203
// NueXini
#include <iostream>
typedef int ElemType;
typedef struct NNode
{
ElemType data;
struct NNode *next;
} Node;
void InitList(Node *&L)
{
L->next = NULL;
}
void TraverseList(Node *L)
{
Node *p = L->next;
while (p)
{
std::cout << p->data << " ";
p = p->next;
}
std::cout << std::endl;
}
bool ListInsert(Node *L, int pos, ElemType item)
{
Node *p = L;
int i = 0;
while (p && i != pos - 1)
{
p = p->next;
i++;
}
if (p == NULL)
{
return false;
}
Node *t = new Node;
t->data = item;
t->next = p->next;
p->next = t;
return true;
}
Node *removeAllKeyItem(Node *L, ElemType item)
{
if (L == NULL)
{
return L;
}
L->next = removeAllKeyItem(L->next, item);
return L->data == item ? L->next : L;
}
int main()
{
Node *a = new Node();
InitList(a);
for (size_t i = 0; i < 10; i++)
{
if (!ListInsert(a, i + 1, i))
{
std::cout << "false" << std::endl;
}
}
for (size_t i = 0; i < 10; i++)
{
if (!ListInsert(a, i + 11, 2))
{
std::cout << "false" << std::endl;
}
}
TraverseList(a);
if (!removeAllKeyItem(a, 2))
{
std::cout << "false" << std::endl;
}
else
{
TraverseList(a);
}
return 0;
}
【第4题】
// NueXini
#include <iostream>
typedef int ElemType;
typedef struct NNode
{
ElemType data;
struct NNode *next;
} Node;
void InitList(Node *&L)
{
L->next = NULL;
}
void TraverseList(Node *L)
{
Node *p = L->next;
while (p)
{
std::cout << p->data << " ";
p = p->next;
}
std::cout << std::endl;
}
bool ListInsert(Node *L, int pos, ElemType item)
{
Node *p = L;
int i = 0;
while (p && i != pos - 1)
{
p = p->next;
i++;
}
if (p == NULL)
{
return false;
}
Node *t = new Node;
t->data = item;
t->next = p->next;
p->next = t;
return true;
}
void ReverseList(Node *L)
{
Node *q, *p = L->next;
L->next = NULL;
while (p)
{
q = p->next;
p->next = L->next;
L->next = p;
p = q;
}
}
int main()
{
Node *a = new Node();
InitList(a);
for (size_t i = 0; i < 10; i++)
{
if (!ListInsert(a, i + 1, i))
{
std::cout << "false" << std::endl;
}
}
TraverseList(a);
ReverseList(a);
TraverseList(a);
return 0;
}
【第5题】
// NueXini
#include <iostream>
typedef int ElemType;
typedef struct NNode
{
ElemType data;
struct NNode *next;
} Node;
void InitList(Node *&L)
{
L->next = NULL;
}
void TraverseList(Node *L)
{
Node *p = L->next;
while (p)
{
std::cout << p->data << " ";
p = p->next;
}
std::cout << std::endl;
}
bool ListInsert(Node *L, int pos, ElemType item)
{
Node *p = L;
int i = 0;
while (p && i != pos - 1)
{
p = p->next;
i++;
}
if (p == NULL)
{
return false;
}
Node *t = new Node;
t->data = item;
t->next = p->next;
p->next = t;
return true;
}
Node *removeRangeItem(Node *L, ElemType mink, ElemType maxk)
{
if (L == NULL)
{
return L;
}
L->next = removeRangeItem(L->next, mink, maxk);
if (L->data > mink && L->data < maxk)
{
return L->next;
}
else
{
return L;
}
}
int main()
{
Node *a = new Node();
ElemType min = 2;
ElemType max = 6;
InitList(a);
for (size_t i = 0; i < 10; i++)
{
if (!ListInsert(a, i + 1, i))
{
std::cout << "false" << std::endl;
}
}
TraverseList(a);
if (!removeRangeItem(a, min, max))
{
std::cout << "false" << std::endl;
}
else
{
TraverseList(a);
}
return 0;
}
【第6题】
/*
假设以 I 和 O 分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为
仅有 I 和 O 组成的序列,可以操作的序列为合法序列,否则称为非法序列。如 IOIIOIOO、IIIOOIOO 是
合法的;而 IOOIOIIO、IIIOIOIO 不合法。写出一个算法,判定给定的操作序列是否合法。若合法则返回 1,
否则返回 0(假定被判定的操作序列已存入一维数组 char 型数组 ch[] 中,操作序列以 "\0" 为结束符)。
*/
#include <stdio.h>
/**
* 顺序栈最大存储的元素个数
*/
#define MAXSIZE 100
/**
* 顺序栈结构体定义
*/
typedef struct
{
/**
* 数据域,数组,用来存储栈中元素
*/
char data[MAXSIZE];
/**
* 指针域,表示栈顶指针,实际上就是数组下标
*/
int top;
} SeqStack;
/**
* 初始化顺序栈,即将栈顶指针指向 -1 表示空栈
* @param stack 顺序栈
*/
void init(SeqStack *stack)
{
// 设定让栈顶指针指向 -1 表示为栈空
stack->top = -1;
}
/**
* 判断顺序栈是否为空
* @param stack 顺序栈
* @return 如果顺序栈为空则返回 1,否则返回 0
*/
int isEmpty(SeqStack stack)
{
// 只需要判断栈顶指针是否等于 -1 即可,如果是空栈则返回 1,不是空栈则返回 0
if (stack.top == -1)
{
return 1;
}
else
{
return 0;
}
}
/**
* 将元素入栈
* @param stack 顺序栈
* @param ele 元素值
* @return 如果栈满则返回 0 表示入栈失败;如果插入成功则返回 1
*/
int push(SeqStack *stack, char ele)
{
// 1.参数校验,如果栈满则不能入栈元素
if (stack->top == MAXSIZE - 1)
{
// 如果栈满,则返回 0,表示不能入栈
return 0;
}
// 2.先将栈顶指针加一,指向新空数组位置
stack->top++;
// 3.将新元素值填充到新位置中
stack->data[stack->top] = ele;
return 1;
}
/**
* 将元素出栈
* @param stack 顺序栈
* @param ele 用来保存出栈的元素
* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功
*/
int pop(SeqStack *stack, char *ele)
{
// 1.参数校验,栈空不能出栈
if (stack->top == -1)
{
// 栈空,没有元素可出栈
return 0;
}
// 2.用 ele 来保存顺序栈栈顶元素
*ele = stack->data[stack->top];
// 3.然后栈顶指针减一,表示出栈一个元素
stack->top--;
return 1;
}
/**
* 获取栈顶元素,但不出栈
* @param stack 顺序栈
* @param ele 用来保存出栈元素
* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功
*/
int getTop(SeqStack stack, char *ele)
{
// 1.参数校验,如果栈空则不能出栈
if (stack.top == -1)
{
// 栈空,没有元素可出栈
return 0;
}
// 2.保存栈顶元素返回
*ele = stack.data[stack.top];
return 1;
}
/**
* 判断指定操作序列是否合法
* @param options 操作序列数组,由 I 和 O 组成
* @param n 数组长度
* @return 如果操作序列合法则返回 1,否则返回 0 表示不合法
*/
int isLegal(char options[], int n)
{
// 0.声明栈并初始化栈,用来作为解题的辅助数据结构
SeqStack stack;
init(&stack);
// 1.遍历字符数组 options 中所有字符
for (int i = 0; i < n; i++)
{
// 局部变量,记录当前的数组元素
char c = options[i];
// 1.1 如果是 I 操作,则将其入栈
if (c == 'I')
{
push(&stack, c);
}
// 1.2 如果是 O 操作,则需要根据不同情况进行处理
else if (c == 'O')
{
// 1.2.1 如果是空栈,则表示此时 O 操作比 I 操作,那么一定不合法,返回 0
if (isEmpty(stack))
{
return 0;
}
// 1.2.2 如果不是空栈,则将栈顶元素出栈,即 O 操作与 I 操作相互抵消一次
else
{
char top;
pop(&stack, &top);
}
}
}
// 2.循环结束后,判断栈中是否还有元素,如果还有元素则表示 I 操作比 O 操作多,不合法;如果栈空则表示合法
if (isEmpty(stack))
{
return 1;
}
else
{
return 0;
}
}
/**
* 判断指定操作序列是否合法
* @param options 操作序列数组,由 I 和 O 组成
* @param n 数组长度
* @return 如果操作序列合法则返回 1,否则返回 0 表示不合法
*/
int isLegal2(char options[], int n)
{
int i = 0; // 表示 I 操作的个数
int o = 0; // 表示 O 操作的个数
for (int m = 0; m < n; m++)
{
if (options[m] == 'I')
{
i++;
}
else if (options[m] == 'O')
{
o++;
// 如果出栈操作 O 的次数大于入栈操作 I 的次数,那么必然不是合法序列
if (o > i)
{
return 0;
}
}
}
// 扫描完成后,比较 i 和 o 的次数,如果相等则表示序列合法,否则表示 I 操作的次数大于 O 操作的次数则不合法
if (i != o)
{
return 0;
}
else
{
return 1;
}
}
int main()
{
int result;
char arr1[] = "IOIIOIOO";
int n1 = 8;
result = isLegal(arr1, 8);
printf("%s 是否是合法的操作序列:%d\n", arr1, result);
char arr2[] = "IIIOOIOO";
int n2 = 8;
result = isLegal(arr2, 8);
printf("%s 是否是合法的操作序列:%d\n", arr2, result);
char arr3[] = "IOOIOIIO";
int n3 = 8;
result = isLegal(arr3, 8);
printf("%s 是否是合法的操作序列:%d\n", arr3, result);
char arr4[] = "IIIOIOIO";
int n4 = 8;
result = isLegal(arr4, 8);
printf("%s 是否是合法的操作序列:%d\n", arr4, result);
}
enjoy it ~