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将成为您的助力!!!

浙公网安备 33010602011771号