2011-11-26 215 views
0

經過很多努力,我已經設法將一個從我的鏈接列表中刪除某個節點的函數拼湊在一起。但是,出於純粹的興趣,我想了解如何從列表中刪除第一個節點,即頭部。刪除鏈接列表中的節點

我的程序要求刪除一個字母,例如。 你好存儲在列表中,用戶輸入H進行刪除,所以現在列表是ello 現在用我的代碼,程序崩潰了,就好像H被刪除一樣,沒有頭,程序也沒有'不知道去哪裏尋找名單。

下面是我目前的實現,任何線索或提示如何修改此代碼(我想保持它類似於我的),以允許頭節點刪除將不勝感激!

編輯:在回答下面

FullList DeleteNode(FullList temp, char c) { 
FullList remember; 
FullList ptr; 
while (temp.head->c != c) { 
    remember.head = temp.head; 
    temp.head = temp.head->next; 
} 
ptr.head = temp.head->next; 
free(temp.head); 
remember.head->next = ptr.head; 
return temp; 
} 

int main(void) { 
FullList List; 
char c, s; 
List.head = NULL; 

while ((c=getchar()) != '.') { 
    List = addToEnd(List, c); 
} 
scanf(" %c", &s); 
List = DeleteNode(List, s); 
while (List.head != NULL) { 
    printf("%c", List.head->c); 
    List.head = List.head->next; 
} 
return 0; 
} 

typedef struct List { 
char c; 
struct List *next; 
}List; 

typedef struct { 
List *head; 
List *tail; 
}FullList; 

List *insertList(char c, List *t1) { 
    List *t = (List*)calloc(1, sizeof(List)); 
    t->c = c ; 
    t->next = t1; 
return t; 
} 

FullList addToEnd(FullList c, char element) { 
if (c.head == NULL) { 
    c.head = c.tail = insertList(element, NULL); 
}else { 
    c.tail->next = insertList(element, NULL); 
    c.tail = c.tail->next; 
} 
return c; 
} 

void DeleteNode(FullList temp, char c) { 
FullList remember; 
FullList ptr; 
while (temp.head->c != c) { 
    remember.head = temp.head; 
    temp.head = temp.head->next; 
} 
ptr.head = temp.head->next; 
free(temp.head); 
remember.head->next = ptr.head; 
} 


int main(void) { 
FullList List; 
char c, s; 
List.head = NULL; 

while ((c=getchar()) != '.') { 
    List = addToEnd(List, c); 
} 
scanf(" %c", &s); 
DeleteNode(List, s); 
while (List.head != NULL) { 
    printf("%c", List.head->c); 
    List.head = List.head->next; 
} 
return 0; 
} 

回答

1

如果不更改現有的代碼,則無法執行此操作。

您正在將FullList結構傳遞給您的DeleteNode()函數。這意味着對該結構的任何更改在main中都不可見 - 函數獲得副本

你需要改變DeleteNode()接受指針:調用它時

void DeleteNode(FullList *temp, char c) 

然後main()你會怎麼做:

DeleteNode(&List, s); 

通過這樣做,你可以改變的temp->head的價值你的功能將會回到main()

temp->head = temp->head->next; 

編輯:你需要的邏輯是:

  • 檢查,看是否temp->head->c == c
  • 如果是的話,有temp->head->next
  • 其他分配temp->head更換temp->head到一個臨時指針*previous。將temp->head->next分配給指針*current。遍歷列表,移動兩個指針。當您在current->c中找到匹配項時,將current->next指定爲previous->nextfree(),current節點。
+0

我按照您的建議修改了代碼,但是現在,它會刪除所有內容,直到輸入的字母爲止。即Abcde,輸入c,de打印 – PnP

+0

如果可能,請參閱我的編輯,我已返回FullList而不是使用指針,但得到相同的結果,它會刪除所有內容,直到我輸入的字母爲止。 – PnP

+0

@ user1048116 - 我現在解釋了改變'temp-> head'的值,我沒有爲你做功課;)你需要構建從頭部開始尋找匹配的邏輯。作爲一個提示,你將需要兩個指針 - 「* previous」和「* current」。您需要從頭開始,跟蹤前一個和當前節點,並在'current-> c'中查找您的匹配項。當你找到你想要刪除的節點時,你必須將'current-> next'分配給'previous-> next',然後''free''當前'節點。沒有必要從這個函數中返回任何東西 - 你正在通過指針修改結構體 –

1

現在是,裏面DeleteNode的方式,當你改變的說法,它只是改變了局部變量,而不是外面的一個功能。

您可能已通過指針FullList傳遞給DeleteNode,這樣做是爲了它的修改將是可見的來電,或修改本地一個並返回,調用者必須將返回FullList其名單。

無論採用哪種方式,DeleteNode所做的更改都必須對調用者可見。

+0

請看我的編輯和評論在上面的答案。 :) – PnP

+0

@ user1048116正如布賴恩羅奇所說的,你必須有兩個指針(一個指向當前指針,一個指向前一指針,其下一個指針必須修復),或者只執行'temp.head-> next-> c'而不是'temp.head-> c',並且有一個特殊情況,其中'head-> c'是所需的字符。 –

+0

感謝您的建議,事實上,我設法通過添加一條IF語句來處理當前代碼,如果搜索到的內容碰巧是頭節點,並將其餘代碼放入ELSE子句中。 – PnP