2016-10-09 44 views
1

我想在C中設置一個雙向指針隊列。 到目前爲止,我有推送功能的工作和測試。我的問題似乎是在兩端彈出條目。指針出隊 - 指針訓練

#include <stdlib.h> 
#include <stdio.h> 
#include "dequeue.h" 

dequeue* dequeue_create() 
{ 
    return NULL; 
} 
void dequeue_push_front(dequeue** dq, int data) 
{ 
    dequeue* tmp = malloc(sizeof(*tmp)); 
    tmp->data = data; 
    tmp->next=NULL; 
    if((*dq) == NULL) 
    { 
     (*dq) = tmp; 
    } 
    else 
    { 
     if ((*dq)->next == NULL) 
     { 
      (*dq)->next = tmp; 
      tmp->prev = (*dq); 

     } 
     else 
     { 

      dequeue* tmp_it = malloc(sizeof(struct _dequeue_)); 
      tmp_it = (*dq)->next; 
      while(tmp_it->next != NULL) 
      { 
       tmp_it = tmp_it->next; 

      } 
      tmp_it->next = tmp; 
      tmp->prev = tmp_it; 

     } 
    } 
} 

void dequeue_push_back(dequeue** dq, int data) 
{ 
    dequeue* tmp = malloc(sizeof(struct _dequeue_)); 
    tmp->data = data; 
    tmp->prev=NULL; 
    if((*dq) == NULL) 
    { 
     (*dq) = tmp; 
    } 
    else 
    { 

     if ((*dq)->prev == NULL) 
     { 
      (*dq)->prev = tmp; 
      tmp->next = (*dq); 

     } 
     else 
     { 
      dequeue* tmp_it = malloc(sizeof(struct _dequeue_)); 
      tmp_it = (*dq)->prev; 
      while(tmp_it->prev != NULL) 
      { 
       tmp_it = tmp_it->prev; 
      } 
      tmp_it->prev = tmp; 
      tmp->next = tmp_it; 

     } 
    } 
} 

int dequeue_pop_front(dequeue** dq) 
{ 
    dequeue* tmp_get = malloc(sizeof(struct _dequeue_)); 
    int output = 0; 

    if((*dq)->next == NULL) 
    { 
     printf("\ndqnext==null\n"); 
    } 
    else 
    { 
     tmp_get = (*dq); 
     while(tmp_get->next != NULL) 
     { 
      tmp_get= tmp_get->next; 
      output = tmp_get->data; 
     } 
     tmp_get=tmp_get->prev; 
     free(tmp_get->next); 
     tmp_get->next=NULL; 
    } 
    return output; 
} 

int dequeue_pop_back(dequeue** dq) 
{ 
    dequeue* tmp_get = malloc(sizeof(struct _dequeue_)); 
    int output = 0; 

    if((*dq)->prev == NULL) 
    { 
     printf("\ndqprev==null\n"); 
    } 
    else 
    { 
     tmp_get = (*dq); 
     while(tmp_get->prev != NULL) 
     { 

      output = tmp_get->data; 
      tmp_get= tmp_get->prev; 

     } 
     free(tmp_get); 
     tmp_get=NULL; 
    } 
    return output; 
} 

dequeue.h:

#ifndef dequeue_H 
#define dequeue_H 

struct _dequeue_ { 
    struct _dequeue_* next; 
    struct _dequeue_* prev; 
    int data; 
}; 

typedef struct _dequeue_ dequeue; 

dequeue* dequeue_create(); 
void dequeue_destroy(dequeue** queue); 

int dequeue_pop_front(dequeue** dq); 
void dequeue_push_front(dequeue** dq, int data); 

int dequeue_pop_back(dequeue** dq); 
void dequeue_push_back(dequeue** dq, int data); 

#endif /* dequeue_H */ 

的main.c:

int main() 
{ 
    dequeue* dq = dequeue_create(); 

    dequeue_push_front(&dq, 1); 
    dequeue_push_back(&dq, 2); 
    dequeue_push_front(&dq, 3); 
    for (int cnt = 1; cnt <=4; cnt++) 
    { 
     printf("FINAL=%d ", dequeue_pop_front(&dq)); 
    } 


    //TODO : dequeue_destroy(&dq); 

    return 0; 
} 

我非常新的指針,這似乎是我的問題。

我想在彈出函數中做的是遍歷指針到達最後一個指針並釋放最後一個指針。但它似乎並沒有釋放指針。現在嘗試了幾種不同的方式,但似乎沒有一個能夠工作,難道我設置推送功能的方式不可能釋放指針嗎?

任何幫助非常感謝。 歡呼聲

+1

我不明白你爲什麼要在pop裏面調用'malloc()'。這會導致代碼中的內存泄漏。 – zapstar

+0

我想過使用tmp_get作爲tmp指針。修正了這個錯誤* tmp_get =(* dq);並在elses中刪除它。 –

+0

upvote for(almost)http://stackoverflow.com/help/mcve –

回答

0

的推

dequeue_push_front(&dq, 1); 

NULL < - 中間(1) - > NULL

dq指向的中間節點

dequeue_push_front(&dq, 2); 

NULL < - 中(1)< - >右鍵(2) - >如果dq傳遞作爲NULL

NULL NULL

dq仍然指向中間節點,因爲你的代碼只是改變它< - 左(3)< - >中間(1)< - >右(2) - > NULL

dq仍然指向出於同樣的原因

中間節點持久性有機污染物

讓跟隨您的彈出代碼:

tmp_get = (*dq); 
while(tmp_get->next != NULL) 
{ 
    tmp_get= tmp_get->next; 
    output = tmp_get->data; 
} 
tmp_get=tmp_get->prev; 
free(tmp_get->next); 
tmp_get->next=NULL; 

這將導致以下狀態:

NULL < - 左(3)< - > middle(1) - > NULL

dq仍指向中間節點的。接下來,和每個其他時間的功能被執行

if((*dq)->next == NULL) 

的值爲true,導致沒有進一步的變化。

其他問題

正如在評論中指出,有你的流行函數內部內存泄漏。請看下圖:

dequeue* tmp_get = malloc(sizeof(struct _dequeue_)); 
... 
tmp_get = (*dq); 

malloc()被調用時,分配sizeof(struct _dequeue_)字節的內存。返回一個指針,並將其分配給變量tmp_get。然後用不同的指針覆蓋這個指針,這意味着現在有一塊你無法訪問或釋放的分配內存。我看不出有什麼原因需要首先分配這些內存。在深入實際的問題之前,

0

一些提示:

    在dequeue.c
  • ,第一的#include應該是對dequeue.h,因爲這是確保,dequeue.h一種系統的方式包括一切本身的需要。
  • 結構出列應該只是被稱爲出列。 (後面的typedef可以使用相同的名稱 - 這裏沒有問題)

然後,有一些誤解:您的_dequeue_s是出隊的NODES,而不是出隊本身。所以,你應該有兩種結構:

struct dequeue_node { 
     struct dequeue_node * next; 
     struct dequeue_node * prev; 
     int data; 
}; 

struct dequeue { 
     struct dequeue_node * frst; 
     struct dequeue_node * last; 
     size_t size; 
}; 

調用入口FRST(而不是第一)是我個人的風格,它使4個字符長像下一個/上/最後/大小,但是你可以先叫它如果你喜歡。大小不是必需的,但允許O(1)檢索出隊的大小。

這樣,您不必遍歷整個出隊列表,找到它的結尾。

所以,現在你的實際問題:

在創建第一個節點,dequeue_push_front不初始化TMP-> prev(和dequeue_push_back不會初始化下一個TMP->)。所以,你從出發開始就是處於非法狀態。

然後,在考慮「前方」的時候,我想到「第一」,並且假設有下一個。所以,幾乎所有的人都在交換下一個和上一個的意義。假設這一個:

     a    b    c 
       +-------------+ +-------------+ +-------------+ 
       | next = b | | next = c | | next = NULL | 
       | prev = NULL | | prev = a | | prev = b | 
       +-------------+ +-------------+ +-------------+ 

我稱之爲「第一」和c「最後一個」。但是dequeue_push_front嘗試在這個ascii藝術中添加c右邊的一個元素。

考慮到你的命名,推送功能似乎是正確的(除了上面提到的點)。

彈出功能現在有一個錯誤,由 s.b注意到。他再次刪除了他的帖子 Ben Wainwright(他編輯,顯示爲刪除後)。你檢查(* dp) - > next/prev == NULL,如果這是真的,你就保釋出來,但你應該刪除這個節點。因此,對於dequeue_pop_front(在您的實現中):

if ((*dq)->next == NULL) { 
    dequeue * tmp = (*dq); 
    output = tmp->data; 
    (*dq) = (*dq)->prev; 
    if ((*dq)) { 
      (*dq)->next = NULL; 
    } 
    free(tmp); 
} else { 
    ... 

和pop_back反之亦然。

其餘的問題是效率低下和內存泄漏,後者你應該學會使用http://valgrind.org/找到它們,首先,你應該總是問自己,天氣語句可以移出一個循環,喜歡這裏:(再次從dequeue_pop_front):

while(tmp_get->next != NULL) 
    { 
     tmp_get= tmp_get->next; 
     output = tmp_get->data; // this can be moved out 
    } 

輸出變量將被不斷改寫,直至循環結束,所以,把它拿出來:

while(tmp_get->next != NULL) 
    { 
     tmp_get= tmp_get->next; 
    } 
    output = tmp_get->data; // this can be moved out 

所以,最終確定dequeue.c(但你應該真的去做ange with dequeue & dequeue_node):

dequeue* dequeue_create() 
{ 
    return NULL; 
} 
void dequeue_push_front(dequeue** dq, int data) 
{ 
    dequeue* tmp = malloc(sizeof(*tmp)); 
    tmp->data = data; 
    tmp->next=NULL; 
    tmp->prev=NULL; 
    if((*dq) == NULL) 
    { 
     (*dq) = tmp; 
    } 
    else 
    { 
     if ((*dq)->next == NULL) 
     { 
      (*dq)->next = tmp; 
      tmp->prev = (*dq); 

     } 
     else 
     { 

      dequeue* tmp_it = malloc(sizeof(struct _dequeue_)); 
      tmp_it = (*dq)->next; 
      while(tmp_it->next != NULL) 
      { 
       tmp_it = tmp_it->next; 

      } 
      tmp_it->next = tmp; 
      tmp->prev = tmp_it; 

     } 
    } 
} 

void dequeue_push_back(dequeue** dq, int data) 
{ 
    dequeue* tmp = malloc(sizeof(struct _dequeue_)); 
    tmp->data = data; 
    tmp->next=NULL; 
    tmp->prev=NULL; 
    if((*dq) == NULL) 
    { 
     (*dq) = tmp; 
    } 
    else 
    { 

     if ((*dq)->prev == NULL) 
     { 
      (*dq)->prev = tmp; 
      tmp->next = (*dq); 

     } 
     else 
     { 
      dequeue* tmp_it = malloc(sizeof(struct _dequeue_)); 
      tmp_it = (*dq)->prev; 
      while(tmp_it->prev != NULL) 
      { 
       tmp_it = tmp_it->prev; 
      } 
      tmp_it->prev = tmp; 
      tmp->next = tmp_it; 

     } 
    } 
} 

int dequeue_pop_front(dequeue** dq) 
{ 
    dequeue* tmp_get = malloc(sizeof(struct _dequeue_)); 
    int output = 0; 

    if((*dq)->next == NULL) 
    { 
     dequeue * tmp = (*dq); 
     output = tmp->data; 
     (*dq) = (*dq)->prev; 
     if ((*dq)) { 
       (*dq)->next = NULL; 
     } 
     free(tmp); 
    } 
    else 
    { 
     tmp_get = (*dq); 
     while(tmp_get->next != NULL) 
     { 
      tmp_get= tmp_get->next; 
      output = tmp_get->data; 
     } 
     tmp_get=tmp_get->prev; 
     free(tmp_get->next); 
     tmp_get->next=NULL; 
    } 
    return output; 
} 

int dequeue_pop_back(dequeue** dq) 
{ 
    dequeue* tmp_get = malloc(sizeof(struct _dequeue_)); 
    int output = 0; 

    if((*dq)->prev == NULL) 
    { 
     dequeue * tmp = (*dq); 
     output = tmp->data; 
     (*dq) = (*dq)->next; 
     if ((*dq)) { 
       (*dq)->prev = NULL; 
     } 
     free(tmp); 
    } 
    else 
    { 
     tmp_get = (*dq); 
     while(tmp_get->prev != NULL) 
     { 

      output = tmp_get->data; 
      tmp_get= tmp_get->prev; 

     } 
     free(tmp_get); 
     tmp_get=NULL; 
    } 
    return output; 
}