Computer >> 컴퓨터 >  >> 프로그램 작성 >> C++

C++의 단일 연결 목록에서 대체 K 노드 역방향

<시간/>

이 튜토리얼에서는 길이가 N이고 정수 K인 연결 목록 A가 제공됩니다. 각 쌍의 크기가 K인 노드의 대체 쌍을 반대로 해야 합니다. 또한 N은 K로 나눌 수 있다고 가정합니다. 첫 번째 인수는 다음과 같습니다. 연결 목록 A의 헤드 포인터와 두 번째 인수는 정수 K입니다. 예를 들어

입력

5 -> 6 -> 2 -> 8 -> 5 -> 2 -> 4 -> 8 -> 9 -> 6 -> 널 K=2

출력

6 -> 5 -> 2 -> 8 -> 2 -> 5 -> 4 -> 8 -> 6 -> 9 -> null
1 -> 2 -> 5 -> 8 -> 9 -> 6 -> 4 -> 5 -> 8 -> 널 K=3

출력

5 -> 2 -> 1 -> 8 -> 9 -> 6 -> 8 -> 5 -> 4 -> null

해결책을 찾기 위한 접근 방식

반복적 솔루션

  • 반복(또는 루프)당 2K 노드를 트래버스하고 조인 및 테일 포인터를 사용하여 주어진 입력(연결 목록)에 K 노드의 각 쌍의 헤드 및 테일을 기록합니다.

  • 그런 다음 연결 목록의 k 노드를 반대로 하고 역방향 목록의 꼬리 노드를 결합 포인터가 가리키는 초기 연결 목록의 머리 노드와 결합합니다.

  • 그런 다음 현재 포인터를 다음 k 노드로 변경합니다.

  • 일반 목록의 꼬리는 이제 마지막 노드(새 꼬리가 가리키는) 역할을 하고 조인 포인터는 새(역방향) 목록의 머리를 가리키고 병합됩니다. 모든 노드가 동일한 단계를 따를 때까지 이 단계를 반복합니다.

예시

#include 네임스페이스 std;class Node { public:int data; Node* next;};Node* kAltReverse(struct Node* head, int k){ Node* prev =NULL; 노드* curr =헤드; 노드* 온도 =NULL; 노드* 꼬리 =NULL; 노드* newHead =NULL; 노드* 조인 =NULL; 정수 t =0; 동안 (커) { t =k; 조인 =커; 이전 =NULL; while (curr &&t--) { temp =curr->next; 현재->다음 =이전; 이전 =커; 커 =온도; } if (!newHead) newHead =이전; if (꼬리) 꼬리->다음 =이전; 꼬리 =조인; 꼬리 -> 다음 =curr; t =k; 동안 (curr &&t--) { 이전 =curr; curr =curr->다음; } 꼬리 =이전; } return newHead;}void push(Node** head_ref, int new_data){ Node* new_node =new Node(); new_node->data =new_data; new_node->next =(*head_ref); (*head_ref) =new_node;} 무효 printList(노드* 노드){ int count =0; while (노드 !=NULL) { cout <<노드->데이터 <<" "; 노드 =노드->다음; 카운트++; }}int main(void){ 노드* 헤드 =NULL; 정수 나; for (i =6, i <27, i+=3) push(&head, i); 정수 k =3; cout <<"연결리스트가 주어졌을 때 \n"; 인쇄 목록(머리); 머리 =kAltReverse(머리, k); cout <<"\n 연결 목록 수정 \n"; 인쇄 목록(머리); 반환(0);}

출력

주어진 연결 목록24 21 18 15 12 9 6수정된 연결 목록18 21 24 15 12 9 6

재귀 솔루션

  • 시작에서 K 노드를 탐색하고 임시 값을 k+1 번째 노드로 설정

  • 통과한 모든 K 노드를 반대로 합니다.

  • K 노드 쌍의 마지막 노드의 다음 포인터를 temp로 설정합니다.

  • 해당 K 노드 쌍이 건너뛰어야 하는 다음 반복을 건너뜁니다.

  • 마지막 노드에 도달할 때까지 다음 k 노드를 되돌리기 위해 이 모든 단계를 재귀적으로 따릅니다.

의사 코드

reverseAltK(head, k) curr =head prev =null next =null count =0 WHILE count  

예시

#include 네임스페이스 std 사용;/* 링크 목록 노드 */class node{ public:int data; node* next;};/* kAltReverse()를 위한 도우미 함수 */node * _kAltReverse(node ​​*node, int k, bool b);/* 또는 주어진 크기 k의 주어진 연결 목록 그룹을 반대로 합니다. */node *kAltReverse(node ​​*head, int k){ return _kAltReverse(head, k, true);}/* kAltReverse()에 대한 도우미 함수. 세 번째 매개변수 b가 true로 전달된 경우에만 목록의 k 노드를 반전시킵니다. 그렇지 않으면 포인터를 k 노드 앞으로 이동하고 재귀적으로 자체 호출 */node * _kAltReverse(node ​​*Node, int k, bool b){ if(Node ==NULL) return NULL; 정수 개수 =1; 노드 *이전 =NULL; 노드 *현재 =노드; 노드 *다음; /* 루프는 두 가지 목적을 수행합니다. 1) b가 참이면 k 노드를 반대로 합니다. 2) b가 거짓이면 현재 포인터를 이동합니다. */ while(current !=NULL &&count <=k){ next =현재->다음; /* b가 true인 경우에만 노드를 반전시킵니다.*/ if(b ==true) current->next =prev; 이전 =현재; 현재 =다음; 카운트++; } /* 3) b가 true이면 node는 k번째 노드입니다. 따라서 노드 뒤에 나머지 목록을 첨부하십시오. 4) 부착 후 새로운 헤드를 반환 */ if(b ==true){ Node->next =_kAltReverse(current, k, !b); 이전 반환; } /* b가 true가 아니면 prev 뒤에 나머지 목록을 첨부합니다. 따라서 나머지 목록을 prev */ else{ prev->next =_kAltReverse(current, k, !b); 반환 노드; }}/* 유틸리티 기능 *//* 노드를 푸시하는 함수 */void push(node** head_ref, int new_data){ /* 노드 할당 */ node* new_node =new node(); /* 데이터를 넣습니다 */ new_node->data =new_data; /* 새 노드에서 이전 목록을 링크합니다. */ new_node->next =(*head_ref); /* 새 노드를 가리키도록 헤드를 이동합니다. */ (*head_ref) =new_node;}/* 연결 목록을 인쇄하는 함수 */void printList(node ​​*node){ int count =0; while(노드 !=NULL){ cout <<노드->데이터 <<" "; 노드 =노드->다음; 카운트++; }}// Driver Codeint main(void){ /* 빈 목록으로 시작 */ node* head =NULL; 정수 나; // 리스트 생성 1->2->3->4->5...... ->20 for(i =20; i> 0; i--) push(&head, i); cout <<"연결리스트가 주어졌을 때 \n"; 인쇄 목록(머리); 머리 =kAltReverse(머리, 3); cout <<"\n연결된 목록 수정 \n"; 인쇄 목록(머리); 반환(0);}

출력

주어진 연결 목록1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20연결 목록 수정3 2 1 4 5 6 9 8 7 10 11 12 12 35 164 

결론

이 자습서에서는 단일 연결 목록에서 대체 k 노드를 반전하고 C++ 코드에서 의사 코드를 구현하는 방법을 배웠습니다. 우리는 또한 자바, 파이썬 및 기타 언어로 이 코드를 작성할 수 있습니다. 이 접근 방식에서는 재귀를 사용하여 대체 K 노드를 역전시키고 나머지 노드를 건너뜁니다. 이 튜토리얼이 도움이 되기를 바랍니다.