//This function reverses part of a doubly linked list, and modify the startPoint
//and endPoint pointers to the new start and end.
void List<T>::reverse(ListNode *& startPoint, ListNode *& endPoint) {
if ((startPoint==NULL)||(endPoint==NULL)||(startPoint==endPoint)) return;
ListNode* tmp=NULL;
ListNode* crr=startPoint;
ListNode* endNext=endPoint->next;
ListNode* startPrev=startPoint->prev;
while(crr!=endNext){
tmp=crr->prev;
crr->prev=crr->next;
crr->next=tmp;
crr=crr->prev;
}
if (startPrev!=NULL) startPrev->next=endPoint;
//problem happens after this line
if (endNext!=NULL) endNext->prev=startPoint;
tmp=startPoint->next;
startPoint->next=endPoint->prev;;
endPoint->prev=tmp;
tmp=startPoint;
startPoint=endPoint;
endPoint=tmp;
}
После того, как я запустил это в GDB, я обнаружил, что когда я делал "startPrev-> next = endPoint", он фактически менял startPointer. Но я хочу изменить только следующий указатель. Похоже, что следующий указатель действовал так, как будто это ссылка на startPointer, чего не должно происходить. Что не так с моим кодом?
Breakpoint 2, List<int>::reverse (this=0x7ffffffee180, startPoint=@0x623260: 0x6232c0,
endPoint=@0x7ffffffee188: 0x6232e0) at ./List.hpp:126
126 while(crr!=endNext){
(gdb) next
133 if (startPrev!=NULL) startPrev->next=endPoint;
(gdb) info args
this = 0x7ffffffee180
startPoint = @0x623260: 0x6232c0
endPoint = @0x7ffffffee188: 0x6232e0
(gdb) info locals
tmp = 0x6232c0
crr = 0x0
endNext = 0x0
startPrev = 0x623260
(gdb) next
134 if (endNext!=NULL) endNext->prev=startPoint;
(gdb) info locals
tmp = 0x6232c0
crr = 0x0
endNext = 0x0
startPrev = 0x623260
(gdb) info args
this = 0x7ffffffee180
startPoint = @0x623260: 0x6232e0
endPoint = @0x7ffffffee188: 0x6232e0
Также подумайте, можете ли вы адаптировать этот трюк с указателем на указатель, чтобы уменьшить объем бухгалтерского учета, который вам необходимо поддерживать.
Используйте ручку и бумагу и нарисуйте все свои узлы и указатели. Это лучший способ работать со структурами указателей.