算法笔记.胡凡 第七章 数据结构专题 & 第八章 搜索专题

8 篇文章 0 订阅
8 篇文章 0 订阅

7.3 链表处理

7.3.1 链表概念

struct node {
    typename data;//数据域
    node* next;//指针域
};

链表可以分为带头结点的和不带头结点的链表。

7.3.2 为链表节点分配内存空间

1. malloc函数

typename* p = (typename*) malloc(sizeof(typename));
int* p = (int*) malloc(sizeof(int));
int* p = (int*) malloc(10000*sizeof(int));//申请的动态数组过大容易失败

2.new运算符

typename* p = new typename;
int* p = new int;
node* p = new node;

3. 内存释放

malloc函数申请的内存使用free函数释放

typename* p = (typename*) malloc(sizeof(typename));
free(p);

new运算符申请的内存使用delete运算符释放

typename* p = new typename;
delete p;

7.3.3 链表的基本操作

1.插入

//将x插入以head为头结点的链表的第pos个位置上
void insert(node* head, int pos, int x) {
    node* p;
    for (int i = 0; i < pos - 1; i++) {
        p = p->next;
    }
    node* q = new node;
    q->data = x;
    q->next = p->next;
    p-> next = q;
}

2.删除

//删除以head为头结点的链表中所有数据域为x的节点
void del(node* head, int x) {
    node* p = head->next;
    node* pre = head;
    while(p != NULL) {
        if(p->data == x) {
            pre->next = p->next;
            delete(p);
            p = pre->next;
        }else {
            pre = p;
            p = p->next;
        }
    }
}
           

7.4.3 静态链表

struct Node {
    typename data;
    int next;
}node[size];

【PAT A1032】

To store English words, one method is to use linked lists and store a word letter by letter. To save some space, we may let the words share the same sublist if they share the same suffix. For example, loading and being are stored as showed in Figure 1.

fig.jpg

Figure 1

You are supposed to find the starting position of the common suffix (e.g. the position of i in Figure 1).

Input Specification:

Each input file contains one test case. For each case, the first line contains two addresses of nodes and a positive N (≤105), where the two addresses are the addresses of the first nodes of the two words, and N is the total number of nodes. The address of a node is a 5-digit positive integer, and NULL is represented by −1.

Then N lines follow, each describes a node in the format:

Address Data Next

whereAddress is the position of the node, Data is the letter contained by this node which is an English letter chosen from { a-z, A-Z }, and Next is the position of the next node.

Output Specification:

For each case, simply output the 5-digit starting position of the common suffix. If the two words have no common suffix, output -1 instead.

Sample Input 1:

11111 22222 9
67890 i 00002
00010 a 12345
00003 g -1
12345 D 67890
00002 n 00003
22222 B 23456
11111 L 00001
23456 e 67890
00001 o 00010
结尾无空行

Sample Output 1:

67890
结尾无空行

Sample Input 2:

00001 00002 4
00001 a 10001
10001 s -1
00002 a 10002
10002 t -1
结尾无空行

Sample Output 2:

-1
结尾无空行
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 100010;
struct NODE{
    char data;
    int next;
    bool flag;//节点是否在第一条链表出现
}node[maxn];
int main() {
    for (int i = 0; i < maxn; i ++ ){
        node[i].flag = false;
    }
    int s1, s2, n;
    if(scanf("%d%d%d", &s1, &s2, &n)){};
    int address,next;
    char data;
    for (int i = 0; i < n; i ++) {
           if(scanf("%d %c %d", &address, &data, &next)){};
        node[address].data = data;
        node[address].next = next;
    }
    int p;
    for (p = s1; p != -1; p = node[p].next) {
        node[p].flag = true;
    }
    for (p = s2; p != -1; p = node[p].next) {
        if(node[p].flag == true) break;
    }
    if(p != -1){
        printf("%05d\n",p);
    }else{
        cout<<"-1"<<endl;
    }
    return 0;
}

7.4.4 静态链表解题思路

①定义静态链表

struct Node{
    int address;//结点地址
    typeName data;//数据域
    int next;//指针域
    XXX;//结点的某个性质
};//node[100000];

②静态链表初始化,初始化XXX字段。例如对结点是否在链表上来说,可以初始化为0(false),表示结点不在链表上。

③根据链表的首节点的地址,开始遍历整个链表。遍历过程对结点的性质XXX进行标记,并且对有效结点个数进行计数count。

④由于使用静态链表,是直接采用地址映射的方式,这样会使得数组下标不连续,而且很多时题目给出的节点并不都是有效结点。为了能够可控的访问有效结点,可以先对数组排序,然后把有效结点移动到数组左端。这样就可以使用第3步得到的count访问他们。

排序的时候可以借助字段XXX,无效的节点的XXX字段可以设置的比较小。

bool cmp {
    if (a.xxx == -1 || b.xxx == -1) {
        return a.xxx > b.xxx;
    } else {
        //第二级排序
    }
}

⑤经历步骤4之后,链表中的有效结点都在数组左端了,且已经按照结点性质排好序。

【PAT A1052】Linked List Sorting

A linked list consists of a series of structures, which are not necessarily adjacent in memory. We assume that each structure contains an integer key and a Next pointer to the next structure. Now given a linked list, you are supposed to sort the structures according to their key values in increasing order.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive N (<105) and an address of the head node, where N is the total number of nodes in memory and the address of a node is a 5-digit positive integer. NULL is represented by −1.

Then N lines follow, each describes a node in the format:

Address Key Next

where Address is the address of the node in memory, Key is an integer in [−105,105], and Next is the address of the next node. It is guaranteed that all the keys are distinct and there is no cycle in the linked list starting from the head node.

Output Specification:

For each test case, the output format is the same as that of the input, where N is the total number of nodes in the list and all the nodes must be sorted order.

Sample Input:

5 00001
11111 100 -1
00001 0 22222
33333 100000 11111
12345 -1 33333
22222 1000 12345
结尾无空行

Sample Output:

5 12345
12345 -1 00001
00001 0 11111
11111 100 22222
22222 1000 33333
33333 100000 -1
结尾无空行
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
//第1步
struct Node{
    int address, data, next;
    bool flag;
}node[maxn];
//第4步
bool cmp(Node a, Node b) {
    if (a.flag == false || b.flag == false) {
        return a.flag > b.flag ;
    } else{
        return a.data < b.data;
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    //第2步
    for (int i = 0; i < maxn; i ++) {
        node[i].flag = false;
    }
    int n, begin, address;
    cin >> n >> begin;
    //第3步
    for (int i = 0; i < n; i ++) {
        cin >>address;
        cin >> node[address].data >> node[address].next ;
        node[address].address = address;
    }
    int count = 0, p =begin;
    while(p != -1) {
        node[p].flag = true;
        count ++;
        p = node[p].next;
    }
    if(count == 0) {
        cout<<"0 -1";
    } else {
        //第4步
        sort(node,node+maxn, cmp);
        printf("%d %05d\n",count,node[0].address);
        for (int i = 0; i < count; i ++) {
            if (i != count -1) {
                printf("%05d %d %05d\n",node[i].address, node[i].data, node[i+1].address);
            } else {
                printf("%05d %d -1\n",node[i].address, node[i].data);
            }
        }
    }
    return 0;
}

8.1 深度优先搜索

8.1.1 问题1

 对每件物品都有选和不选两种操作,死胡同就是题目要求的物品总量不能超过V。

每次都需要对物品进行选择,因此DFS函数的参数必须记录当前处理的物品编号的index。同时需要记录当前已选物品的总重量和总价值。


void DFS(int index, int sumW, int sumC) {
    if (index == n) {//死胡同
        if (sumW <= V && sumC > maxValue) {
            maxValue = sumC;
        }
        return;
    }
    DFS(index + 1, sumW, sumC);//不选第index件物品
    DFS(index + 1, sumW + w[index], sumC + c[index]);
}

        

优化后:


void DFS(int index, int sumW, int sumC) {
    if (index == n) {//死胡同
        return;
    }
    DFS(index + 1, sumW, sumC);//不选第index件物品
    if (sumW + w[index] <= V) {
        if(sumC + c[index] > maxValue) {
            maxValue = sumC + c[index];
        }
        DFS(index + 1, sumW + w[index], sumC + c[index]);//选第index件物品
    }
}

8.1.2 问题2

给定N个整数,从中选择K个数,使得这K个数之和恰好等于一个给定的整数X;如果有多种方案,选择出它们中元素平方和最大的一个。数据保证这样的方案唯一。

解析

此处仍然需要记录当前处理的整数编号index,还要一个参数nowK记录当前已经选择的数的个数,另外还需要参数sum和sumSqu记录当前已经选的整数之和与平方和。

//从序列A中n个数选k个数使得和为x,最大平方和为maxSumSqu
int n, k, x, maxSumSqu = -1, A[maxn];
vector<int> temp, ans;//temp存放临时方案,ans存放最大方案

void DFS(int index, int nowK, int sum, int SumSqu) {
    if(nowK == k && sum == x) {
        if(sumSqu > maxSumSqu) {
            maxSumSqu = sumSqu;
            ans = temp;
        }
        return;
    }
    if(index == n || nowK > k || sum > x ) return;
    temp.push_back(A[index]);
    //选index数
    DFS(index + 1, nowk + 1, sum + A[index], sumSqu + A[index] * A[index]);
    temp.pop_back();
    //不选index 数
    DFS(index + 1, nowK, sum, sumSqu);
}

如果题目稍微修改为:每个数可以选多次,则只需要把选index数这行代码改为:

DFS(index, nowK + 1,sum + A[index], sumSqu + A[index] * A[index]);

8.2 广度优先搜索

深度优先搜索模板

void BFS(int s) {
    queue<int> q;
    q.push(s);
    while(!q.empty()) {
        取出队首元素top;
        访问队首元素top;
        将队首元素出队;    
        将top的下一层结点中未曾入队的结点全部入队,并设置为已入队。
    }
}

8.2.1 问题1

#include<cstdio>
#include<queue。
using namespace std;
const int maxn = 100;
struct node {
    int x, y;
}Node;
int n, m;//矩阵大小为n * m
int matrix[maxn][maxn];//01矩阵
bool inq[maxn][maxn] = {false};//标记是否访问过
int X[4] = {0,0,1,-1}
int Y[4] = {1,-1,0,0};
bool judge(int x, int y) {
    if (x >= n || x < 0 || y >= m || y < 0) return false;
    if (matrix[x][y] == 0 || inq[x][y] = true) return false;
    return true;
}
void BFS(int x, int y) {
    queue<node> Q;
    Node.x = x, Node.y = y;
    Q.push(Node);
    inq[x][y] = true;
    while(!Q.empty()) {
        node top = Q.front();
        Q.pop();
        for (int i = 0; i < 4; i ++) {
            int newX = top.x + X[i];
            int newY = top.y + Y[i];
            if(judge(newX,newY)) {
                Node.x = newX, Node.y = newY;
                Q.push(Node);
                inq[newX][newY] = true;
            }
        }
    }
}

int main() {
    scanf("%d%d",&n,&m);
    for (int x = 0; x < n; x++) {
        for (int y = 0; y < m; y ++) {
            scanf("%d",&matrix[x][y]);
        }
    }
    int ans = 0;//块数
    for (int x = 0; x < n; x ++) {
        for (int y = 0; y < m; y ++) {
            if(matrix[x][y] == 1 && inq[x][y] == false) {
                ans ++;
                BFS(x,y);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

 当使用STL的queue时,元素入队的push操作只是制造了该元素的一个副本入队,因此在入队之后对原元素进行修改不会影响队列中的副本。对队列中副本的修改也不会改变原元素。

8.2.2 问题2

 

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 100;
struct node {
    int x, y;
    int step;//步数
}S,T,Node;
int n, m;//矩阵大小为n * m
char maze[maxn][maxn];//迷宫信息
bool inq[maxn][maxn] = {false};//标记是否访问过
int X[4] = {0,0,1,-1}
int Y[4] = {1,-1,0,0};
bool judge(int x, int y) {
    if (x >= n || x < 0 || y >= m || y < 0) return false;
    if (maze[x][y] == '*' || inq[x][y] = true) return false;
    return true;
}
int BFS() {
    queue<node> q;
    q.push(S);
    while(!q.empty()) {
        node top = Q.front();
        q.pop();
        if (top.x == T.x && top.y == T.y) {
            return top.step;
        }
        for (int i = 0; i < 4; i ++) {
            int newX = top.x + X[i];
            int newY = top.y + Y[i];
            if(judge(newX,newY)) {
                Node.x = newX, Node.y = newY;
                Node.step = top.step + 1;
                q.push(Node);
                inq[newX][newY] = true;
            }
        }
    }
    return -1;
}

int main() {
    scanf("%d%d",&n,&m);
    for (int x = 0; x < n; x++) {
        getchar();
        for (int y = 0; y < m; y ++) {
            maze[x][y] = getchar();
        }
        maze[i][m+1] = '\0';
    }
    scanf("%d%d%d",&S.x,&S.y,&T.x,&T.y);
    S.step = 0;
    printf("%d\n",BFS());
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值