簡體   English   中英

鏈表的堆棧實現中的雙指針

[英]Double pointers in stack implementation of linked list

我最近在讀一本書,這是在鏈接列表中實現堆棧的說明。 以下是說明:

typedef struct Element { 
    struct Element *next; 
    void *data;
} Element;

對應於push和pop的原型如下:

void push( Element *stack, void *data );
void *pop( Element *stack );

現在,從適當的功能和錯誤處理方面考慮這些例程中發生了什么。 這兩個操作都會更改列表的第一個元素。 必須修改調用例程的堆棧指針以反映此更改,但是您對傳遞給這些函數的指針所做的任何更改都不會傳播回調用例程。 您可以通過使兩個例程都使用指向堆棧的指針來解決此問題。 這樣,您可以更改調用例程的指針,使其繼續指向列表的第一個元素。 實施此更改將導致以下結果:

void push( Element **stack, void *data );
void *pop( Element **stack );

但是,我想知道的是,需要為堆棧放置雙指針嗎? 我了解雙指針的概念,但是,當使用Element *node1 = (Element *) malloc (sizeof(Element));創建新節點時Element *node1 = (Element *) malloc (sizeof(Element)); ,我們已經有了指向該節點的指針。 為什么不直接發送此指針而不是使用雙指針呢?

因為沒有獨立的Stack對象,所以每次更改堆棧的頂部節點時,對於使用該堆棧的所有內容,都需要更改對該堆棧的主要引用。 這就是為什么需要雙指針的原因-因為堆棧的舊頂部不再有效。

如果您創建了一個頂層堆棧對象,該對象具有指向Element的指針以及其他一些數據(例如element count),則您可以將其作為單個指針發送到push / pop中,因為該對象/結構可以保持不變,只是其中的數據會改變。

// pseudocode
struct Stack {
  Element * top = NULL;
  int size = 0;
}

struct Element {
  Element * next;
  void * data;
}

function push(Stack * stack, void * data) {
  Element * element = new Element(data);
  element->next = stack->top;
  stack->top = element;
  size++;
}

// pop left as an exercise to the reader.. :)

int main(void*) {
    Stack * stack = new Stack;
    push(stack, "foo"); <== no need for double pointer
    pop(stack); 
    printf("%d\n", stack->size);
}

由於pointers概念和passing by reference的常見混淆,這有點令人困惑。

讓我們看一下原始的push功能。 stack參數表示指向堆棧開頭的指針。 該指針由調用者提供。 如果需要修改堆棧的開頭,則push函數將無法執行此操作,因為它是通過value傳遞的 ,即在函數體內,它是原始副本的副本。 pop

用一個例子最容易理解。 假設堆棧的開頭位於地址0x1234 調用push ,調用者將 0x1234傳遞給它。 push可以使用此值執行任何所需的操作,但是它不會更改原始指針的數據,並且更改不會反映在調用者上下文中。

為什么不發送在push內部創建的node1指針: Element *node1 = (Element *) malloc (sizeof(Element)); 那正是您應該做的,但是您仍然需要雙指針:

void push( Element **stack, void *data )
{
    Element *node1 = (Element *) malloc (sizeof(Element));
    node1->data = data;
    node1->next = *stack;
    *stack = node1;
}

如果您嘗試在沒有雙指針的情況下實現此目標,則調用者將看不到更改,並且將保留舊的堆棧指針:

void push( Element *stack, void *data )
{
    Element *node1 = (Element *) malloc (sizeof(Element));
    node1->data = data;
    node1->next = stack;
    stack = node1;         //The data structure was updated but caller won't see it!
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM