几天前我问你为我的问题挑选最好的数据结构。在那段时间里,我也解释了我的问题,并将其描述为:
Self-organising sequence of numbers with big amount of operations on it - best data structure
我已经实现了它,但不幸的是它无法通过几次测试。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int allCharCounter = 0;
struct List_node{
int value;
struct List_node *next;
struct List_node *prev;
};
//inserting at first
void insert(List_node** start, int v){
List_node* newNode = new List_node;
newNode->value = v;
if(*start == NULL){
newNode->next = newNode;
newNode->prev = newNode;
*start = newNode;
}else{
newNode->next = *start;
newNode->prev = (*start)->prev;
(*start)->prev->next = newNode;
(*start)->prev = newNode;
}
}
//getting input
int getNumber(){
int c = getchar_unlocked();
int value = 0;
for(; (c < 48 || c > 57); c = getchar_unlocked());
for(; c > 47 && c < 58 ; c = getchar_unlocked()){
value = 10*value+c-'0';
allCharCounter++;
}
return value;
}
int main(){
int numberOfOperations = getNumber();
struct List_node* list = NULL;
//counter of numbers
int numbersInSeq = 0;
//passing values to list
while(!feof(stdin)){
int number = getNumber();
insert(&list, number);
numbersInSeq++;
}
if(list !=NULL){
while(numberOfOperations-- != 0){
int c = list->value;
//insert - X
if(c & 1){
List_node* newNode = new List_node;
newNode->value = c-1;
newNode->prev = list;
newNode->next = list->next;
list->next->prev = newNode;
list->next = newNode;
numbersInSeq++;
int moveNext = c%numbersInSeq;
//int movePrev = numbersInSeq - moveNext;
for(int i = 0; i < moveNext; i++){
list = list->next;
}
}else{
//remove - R
c = list->next->value;
List_node* tmp = list->next;
list->next = tmp->next;
list->next->prev = list;
tmp->next = NULL;
tmp->prev = NULL;
free(tmp);
numbersInSeq--;
int moveNext = c%numbersInSeq;
//int movePrev = numbersInSeq - moveNext;
//moving my list (POS)
for(int i = 0; i < moveNext; i++){
list = list->next;
}
}
}
//printing output
for(int i = 0; i < numbersInSeq; i++){
fprintf(stdout, "%d",list->value);
if(i != numbersInSeq-1){
fprintf(stdout, "%c",' ');
}
list = list->next;
}
}else{
//in case of empty list return -1
fprintf(stdout, "%d", -1);
}
fprintf(stdout, "%c",'\n');
fprintf(stdout, "%d",allCharCounter);
}
此代码使用循环双向链表,输出始终是正确的,但正如我之前所说,它对于某些测试来说太慢了。你也可能看到我错误地使用next实现移动列表(POS)。所以我想出了这个:
int moveNext = c%numbersInSeq;
int movePrev = numbersInSeq - moveNext;
if(moveNext < movePrev){
for(int i = 0; i < moveNext; i++){
list = list->next;
}
}else{
for(int i = 0; i < movePrev; i++){
list = list->prev;
}
}
在X和R方法中递增和递减 numbersInSeq 后立即注入。变量 moveNext 是使用next将指针移动到所需位置所需的迭代次数。所以它的差异和 numbersInSeq 是由prev的运动。因此,我知道什么更有效,使用 next 或 prev 移动它。
我在50个数字的例子中进行了测试,输出正确。迭代次数较小:
w / o - 13001
with - 570
不仅在那里还没有通过一次测试,但是对于另一次测试来说它太慢了(虽然我不确切知道那里有什么,但我可以告诉你那个文件它的大小约为34mb)。
也许你可以看到我在这里错过了/写得不好/不了解结构。是否有可能以某种方式优化我的代码更快?
答案 0 :(得分:0)
请查看您之前的问题。您标记为正确的答案实际上是不正确的:您只需要一个单链接的循环列表,因为您总是向前移动而不是向后移动。
显然,代码中的运算符new
和delete
(在您的情况下为free
)会影响性能。基本上,内存分配很慢,如果你想通过一些性能测试,你应该避免它。
有多种技术可以避免内存分配。最简单的方法是使用自由列表元素维护另一个free_list
。
所以你应该编写一个函数来代替new
:
free_list
为NULL
free_list
free_list
= n-&gt; next 而不是delete
或free
你应该写一个函数:
free_list
free_list
= node_to_free //即将节点释放到空闲列表这两项更改应该会为您带来显着的性能提升。如果通过测试是不够的,请在SO上提出更多建议;)