2.2课后题
个人学习所记录笔记,便于复习查看,如有错误,请见谅。
代码均为自己的思路,与标准答案有差异
前半部分为基本的添删改查方法,便于课后题的调用
后半部分为课后题代码
#include <iostream>
#include <map>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int MaxSize =50;
//静态分配
struct SeqList {
int data[MaxSize];
int length;
};
//初始化
void InitList(SeqList& L) {
for (int i = 0; i <MaxSize; i++) {
L.data[i] = 0;
}
L.length = 0;
}
//插入操作
bool ListInsert(SeqList& L, int i, int e) {
//如果插入位置不对
if (i<1 || i>L.length + 1)
return false;
//如果数组已满
if (L.length > MaxSize)
return false;
//正常操作
//先对i后面的数后移
for (int j = L.length; j >= i; j--) {
L.data[j] = L.data[j - 1];
}
//i是位置,i-1是下标
L.data[i-1] = e;
L.length++;
return true;
}
//删除操作
bool ListDelete(SeqList& L, int i, int &e) {
//首先判断是否合法
if (i<1 || i>L.length)
return false;
//得到删除的元素
e =L.data[i - 1] ;
for (int j = i; j < L.length; j++) {
L.data[j - 1] = L.data[j];
}
L.length--;
return true;
}
//按位查找
void ListGetELem(SeqList L, int i) {
cout<< L.data[i - 1]<<endl;
}
//按值查找
void ListLocateElem(SeqList L, int x) {
bool found = false;
for (int i = 0; i < L.length; i++) {
if (L.data[i] == x) {
cout << "该元素在第" << i + 1 << "位" << endl;
found = true;
break; // 找到了就退出循环
}
}
if (!found) {
cout << "没有找到元素" << endl;
}
}
//打印顺序表的元素
void print(SeqList L) {
cout << "此时表中数据为:" << endl;
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
}
// 课后习题
// ///
//例题1
void test01(SeqList& L) {
cout << "执行例题1:" << endl;
if (L.length == 0) {
cout << "表为空" << endl;
return;
}
//分别用来记录最小值和他的位置
int mi=L.data[0];
int idx=0;
for (int i = 1; i < L.length; i++) {
if ( L.data[i]<=mi) {
mi = L.data[i];
idx = i;
}
}
int e = mi;
L.data[idx] = L.data[L.length - 1];
cout <<" 最小的值为:" << e << endl;
print(L);
}
//例题2 逆序排列表中数据
void test02(SeqList& L) {
for (int i = 0, j = L.length - 1; i < j; i++, j--) {
int temp=L.data[i];
L.data[i] = L.data[j];
L.data[j] = temp;
}
print(L);
}
//例题3,删除值为x的值
void test03(SeqList& L, int x) {
int k = 0;
for (int i = 0; i < L.length; i++) {
//如果查到了
if (L.data[i] != x) {
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
}
//例题4,删除s,t之间的所有值
void test04(SeqList& L, int s, int t) {
int k = 0;
if(L.length == 0){
cout << " 顺序表为空"<<endl;
}
else if (s > t) {
cout << " 定值不合理"<<endl;
}
else
{
for (int i = 0; i < L.length; i++) {
int a = L.data[i];
//不在这个区间
if (a<s || a>t) {
L.data[k] = a;
k++;
}
}
L.length = k;
}
}
//例题5,删除表中重复元素
void test05(SeqList& L) {
int k = 0;
map<int, int> mp;
for (int i = 0; i < L.length; i++) {
mp[L.data[i]]++;
}
for (auto j : mp) {
L.data[k] = j.first;
k++;
}
L.length = k;
}
//例题6 ,将两个有序顺序表合成一个
// 这个算法很典型,需要牢固掌握
void test06(SeqList& A, SeqList& B, SeqList& C) {
InitList(A);
//此时a表中数据为1 3 5 7
ListInsert(A, 1, 1);
ListInsert(A, 2, 3);
ListInsert(A, 3, 5);
ListInsert(A, 4, 7);
InitList(B);
//此时b表中数据为2 4 6
ListInsert(B, 1, 2);
ListInsert(B, 2, 4);
ListInsert(B, 3, 6);
//将其合并到c表中,结果应该为1 2 3 4 5 6 7
InitList(C);
int i = 0, j = 0, k = 0;
while (i < A.length && j < B.length) {
if (A.data[i] <= B.data[j]) {
C.data[k++] = A.data[i++];
}
else {
C.data[k++] = B.data[j++];
}
}
// 将剩余元素添加到结果顺序表 C
while (i < A.length) {
C.data[k++] = A.data[i++];
}
while (j < B.length) {
C.data[k++] = B.data[j++];
}
C.length = k; // 更新结果顺序表 C 的长度
cout << "a中数据为" << endl;
print(A);
cout << "b中数据为" << endl;
print(B);
cout << "c中数据为" << endl;
print(C);
}
//例题7,实际上就是数组部分反转
//可以利用vector数组的reverse方法
void test07() {
// 前部分长度为3,后面为4
vector<int> a = { 1, 2, 3, 4, 5, 6, 7 };
// 将前部分反转
reverse(a.begin(), a.begin() + 3); // 3 2 1 4 5 6 7
// 将后部分反转
reverse(a.begin() + 3, a.end()); // 3 2 1 7 6 5 4
// 将整个数组反转
reverse(a.begin(), a.end()); // 4 5 6 7 1 2 3
// 输出结果以验证
for (int num : a) {
cout << num << " ";
}
cout << endl;
}
//例题8 查找数据,找到交换相邻位置,找不到插入最后
//这段代码也能完成,但是不是最快的
void test08(SeqList& L, int x) {
int i;
bool flag = 0;
//如果找到了
for (i = 0; i < L.length; i++) {
if (L.data[i] == x) {
if (i < L.length - 1) {
int temp = L.data[i];
L.data[i] = L.data[i + 1];
L.data[i + 1] = temp;
flag = 1;
}
break;
}
else if (L.data[i] > x) {
break;
}
}
//如果没有找到
if (flag == 0) {
if (i == L.length || L.data[i] > x) {
// 插入元素
if (L.length >= MaxSize) {
cout << "顺序表已满,无法插入元素" << endl;
return;
}
for (int j = L.length; j > i; j--) {
L.data[j] = L.data[j - 1];
}
L.data[i] = x;
L.length++;
}
}
}
//例题9 输出三个数组中相同的元素
//另一种做法,遍历三个数组中的数据到map函数中,输出map中值为3的数据,但是该方法时间复杂度较高
void test09(int n) {
int a[] = { 1,2,3 };
int b[] = { 2,3,4 };
int c[] = { 2,4,6 };
int i=0, j=0, k=0;//指针
//n代表着判断次数,即最短的数组的长度??
while (i < n && j < n && k < n) {
//如果三个数组元素相同
if (a[i] == b[j] && b[j] == c[k]) {
cout << a[i] << endl;
i++;
j++;
k++;
}
//如果不相同
//最大的数据所指向的下标不动,其他的自增
int ma = max(max(a[i], b[i]), c[i]);
if (a[i] < ma) i++;
if (b[i] < ma) j++;
if (c[i] < ma) k++;
}
}
//例题10 循环左移
//时间和空间复杂度均为on,也可采用例题7的方法,空间复杂度变为o1
void test10() {
vector<int> a = { 1, 2, 3, 4, 5 };
cout << "输入左移次数" << endl;
int p; cin >> p;
// 求出数组a的长度
int len = a.size();
// 元素移动次数
int pp = p % len;
vector<int> b(len);
for (int i = 0; i < len; i++) {
// 计算新位置,并确保索引为正数
int newPos = (i + len - pp) % len;
b[newPos] = a[i];
}
for (int i = 0; i < len; i++) {
cout << b[i] << " ";
}
cout << endl; // 别忘了在输出完后换行
}
//例题11 求两个数列的中位数
//思路:可以把两个数列合成一个,然后求中位数
//也可以用指针依次遍历判断,类似例题9,
void test11() {
//采用思路2
vector<int> a = { 11, 13, 15, 17, 19 };
vector<int> b = { 2, 4, 6, 8, 20, 21 };
double len1 = a.size();
double len2 = b.size();
//向上取整
int len = ceil((len1 + len2) / 2.0); // 确保使用浮点数计算
int i = 0, j = 0, k = 0;
int mi = 0;
while (k < len) {
//防止越界或者一个数组遍历完成
if (i < a.size() && (j >= b.size() || a[i] < b[j])) {
mi = a[i];
i++;
}
else {
mi = b[j];
j++;
}
k++;
}
cout << mi << endl;
}
//例题12 求主元素(数组中数据最多的元素且数量大于一半)
void test12() {
vector<int> a = { 0,5,5,3,5,7,5,5 };
map<int, int> mp;
for (int i = 0; i < a.size(); i++) {
mp[a[i]]++;
}
int n = a.size();
int ma = 0;
int maxnum = -1;
for (auto j : mp) {
if (j.second > ma) {
ma = j.second;
maxnum = j.first;
}
}
if (ma > n / 2) {
//输出ma所对应的那个元素
for (auto j : mp) {
if (j.second == ma)
cout << j.first;
}
}
else {
cout << -1;
}
}
//例题13 找出数组中未出现的最小正整数
void test13() {
vector<int> a = { -5,0,2,3 };
bool vis[100] = { 0 };
for (int i = 0; i < a.size(); i++) {
if (a[i] >= 0) {
vis[a[i]] = 1;
}
}
for (int i = 0; i < a.size(); i++) {
int temp = i;
if (vis[i] == 0) {
cout << temp << endl;
break;
}
}
}
//例题14
void test14() {
vector<int> arr1 = { -1, 0, 9 };
vector<int> arr2 = { -25, -10, 10, 11 };
vector<int> arr3 = { 2, 9, 17, 30, 41 };
sort(arr1.begin(), arr1.end());
sort(arr2.begin(), arr2.end());
sort(arr3.begin(), arr3.end());
int i = 0, j = 0, k = 0;
//最小的值
int min_dist = INT_MAX;
//通过指针对三个数组数据进行遍历
while (i < arr1.size() && j < arr2.size() && k < arr3.size()) {
int dist = abs(arr1[i] - arr2[j]) + abs(arr2[j] - arr3[k]) + abs(arr3[k] - arr1[i]);
if (dist < min_dist) {
min_dist = dist;
}
//将指针(或索引)移动到三个数组中最小元素的位置
if (arr1[i] <= arr2[j] && arr1[i] <= arr3[k]) {
i++;
}
else if (arr2[j] <= arr1[i] && arr2[j] <= arr3[k]) {
j++;
}
else {
k++;
}
}
cout << "最短距离为:" << min_dist << endl;
}
int main() {
SeqList A;
SeqList B;
SeqList C;
SeqList L;
InitList(L);
ListInsert(L, 1, 1);
ListInsert(L, 2, 2);
ListInsert(L, 3, 3);
ListInsert(L, 4, 4);
ListInsert(L, 5, 5);
print(L);
cout << "------" << endl;
//test06(A, B, C);
//test08(L,6);
//test04(L,1,3);
//print(L);
test14();
return 0;
}