LOCATE操作(NOJ第6题)

题目描述

 

思路&前言

  这道题的思路很直观。创建循环双链表、填充数据、根据被访问节点增加访问数、根据访问量进行排序、输出即可。

我写的用到的函数如下

Node *insert(Node *, char x);                //插入数据
void init(Node *head, int n);                //初始化,n代表该链表节点数
void sort(Node *head, int n);                //根据freq排序
void print(Node *head);                    //打印结果
void visitChar(Node *head, char *charArray, int n);   //根据charArray里的数据来增加链表里相应的freq

        唯一比较麻烦的是输入数据为char, 这就意味着我们必须处理好 ' ' 与 '\n' ,当然也不难,加个判断即可

  而我写这个题的题解是为了向您推荐STL。

  STL指的是标准模板库,是C++里的内容。但是!!!对于这些编程题而言,STL意味着你不用写那些数据结构了!

 例如: 队列对应queue, 线性表与栈对应vector, 串对应string,等等

  同时,它还内置了查找算法,排序算法,去重算法,相信我,对于现阶段的您来说,这些算法比您自己写得快得多!

 但是!!!如果您要入坑C++,请慎重慎重再慎重!!!

 大部分你只要把C++当成C with STL就行了。

 下面开始解题

实现

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    char data;
    int freq;
    struct Node *next;
    struct Node *prev;
} Node;

Node *insert(Node *, char x);
void init(Node *head, int n);
void sort(Node *head, int n);
void print(Node *head);
void visitChar(Node *head, char *charArray, int n);

void init(Node *head, int n)
{
    head->next = head;
    head->prev = head;
    head->freq = 0;
    head->data = 0;
    Node *aHead = head;
    int i = 0;
    while (1)
    {
        if (i == n)
        {
            break;
        }
        char c;
        scanf("%c", &c);
        if (c != ' ' && c != '\n')
        {
            aHead = insert(aHead, c);
            i++;
        }
    }
}

void visitChar(Node *head, char *charArray, int n)
{
    Node *aHead = head;
    for (int i = 0; i < n; i++)
    {//找到链表内对应元素,让它的freq++
        aHead = aHead->next;
        while (aHead->data != 0)
        {
            if (aHead->data == charArray[i])
            {
                aHead->freq++;
            }
            aHead = aHead->next;
        }
    }
}

void sort(Node *head, int n)
{//根据freq进行排序
    head = head->next;
    while (head->data != 0)
    {//此排序与选择排序类似,相信您能在课本上找到范例
        Node *max = head;
        Node *sortNext = head->next;
        while (sortNext->data != 0)
        {
            if (sortNext->freq > max->freq)
            {
                max = sortNext;
            }
            sortNext = sortNext->next;
        }
        if (max != head)
        {//这里如果不判断会造成死循环
            //这里是在移动元素,在纸上画画吧,很好懂的
            max->next->prev = max->prev;
            max->prev->next = max->next;
            max->next = head;
            max->prev = head->prev;
            head->prev->next = max;
            head->prev = max;
        }
        head = head->next;
    }
}

Node *insert(Node *node, char x)
{
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = x;
    newNode->freq = 0;
    //下面这一堆是为了插入node元素之后
    newNode->next = node->next;
    newNode->prev = node;
    node->next->prev = newNode;
    node->next = newNode;
    //为什么要返回这个newNode?为了不让它每次插入都找一次链表尾
    return newNode;
}

void print(Node *head)
{//打印输出,没啥可说得
    head = head->next;
    while (head->data != 0)
    {
        printf("%c ", head->data);
        head = head->next;
    }
}

int main()
{
    Node *head = (Node *)malloc(sizeof(Node));
    int n, m;
    char visit[1000] = {0};
    scanf("%d", &n);
    scanf("%d", &m);
    init(head, n);
    int i = 0;
    while (1)
    {
        if (i == m)
        {
            break;
        }
        char c;
        scanf("%c", &c);
        if (c != ' ' && c != '\n')
        {
            visit[i] = c;
            i++;
        }
    }
    visitChar(head, visit, m);
    sort(head, n);
    print(head);
}

  注释在上面很清晰地标注出来了。共138行。下来请看STL版本的

#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

struct Node
{
    char data;
    int frec;
};

int main()
{
    vector<Node> list;
    vector<char> willVisit;
    int n, m;
    cin >> n >> m;
    for (size_t i = 0; i < n; i++)
    {//输入数据
        Node m;
        cin >> m.data;
        list.push_back(m);
    }
    for (size_t i = 0; i < m; i++)
    {//输入数据
        char k;
        cin >> k;
        willVisit.push_back(k);
    }
    for (auto i = willVisit.begin(); i < willVisit.end(); i++)
    {//根据willVisit递增链表中相应元素
        (find_if(list.begin(), list.end(), [&i](Node &m)
                 { return m.data == *i; }))
            ->frec++;
    }
    //排序
    sort(list.begin(), list.end(), [](Node &a, Node &b)
         { return a.frec > b.frec; });
    for (size_t i = 0; i < list.size(); i++)
    {//输出
        cout << list[i].data << " ";
    }
}

  43行,很简洁吧!

  总之,这道题不怎么难,但是如果因为这道题能让您了解到STL,那也算值了!!!

  不过,如果您正在学习数据结构,那么不建议您过度依赖STL,以防止期末上机考试时STL被禁,但如果您在学习算法,那么STL将成为您的助力!!!

  

posted @ 2022-03-15 15:11  帝皇の惊  阅读(115)  评论(0)    收藏  举报