[英]Optimising algorithm of self-organising sequence of numbers implemented on circular doubly linked list
幾天前,我問過您,以便為我的問題選擇最佳的數據結構。 在那個時候,我還解釋了我的問題並將其描述為:
我已經實現了它,但是不幸的是它不能通過幾個測試。 這是我的代碼:
#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方法中遞增和遞減numberInSeq后立即注入。 變量moveNext是通過使用next將指針移動到所需位置所需的多次迭代。 因此,它與numbersInSeq的區別是前移 。 因此,我知道什么更有效,可以使用next或prev進行移動。
我已經用50位數字對示例進行了測試,輸出正確。 迭代次數較小:
不帶-13001
與-570
它不僅沒有再通過一個測試,而且對於另一個測試來說太慢了(盡管我不知道其中到底有什么,但我可以告訴你該文件的大小約為34mb)。
也許您可以在這里看到我錯過的內容/對結構的評價很差/不知道。 是否有可能以某種方式優化我的代碼以使其更快?
請查看您之前的問題。 您標記為正確的答案實際上是不正確的:您所需要的只是一個單鏈接的循環列表,因為您始終向前移動而從不向后移動。
顯然,代碼中的運算符new
和delete
(對於您而言是free
的)對性能的影響最大。 基本上,內存分配很慢,因此如果要通過某些性能測試,則應避免使用它。
有多種技術可以避免內存分配。 最簡單的方法是維護帶有free list元素的另一個free_list
。
因此,您應該編寫一個函數而不是new
:
free_list
為NULL
free_list
free_list
= n->下一個 並且應該delete
函數而不是delete
或free
:
free_list
free_list
= node_to_free //將節點釋放到空閑列表 這兩個更改將顯着提高性能。 如果不足以通過測試,請提供更多關於SO的建議;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.