-
2023-04-1023:00:04 #3780233ㅍ 76.***.207.158 1143
다음은 중간에 낀 노드를 삭제하는 과정입니다. temp->next 노드를 삭제하는게 목표입니다. 물론 c++.
다음중 제대로 삭제하는건 과연 어떤것일까요? 맞다고 생각되는걸 다 고르세요. 틀린것들이 틀린 이유는?Node* temp = current;
1. Node* dummPrv = temp; temp = temp->next; dummPrv->next = temp->next; delete (temp);
2. temp->next = temp->next->next; delete (temp->next);
3. temp->next = temp->next->next; Node* dumm=temp->next; dumm=NULL; delete (dumm);
4. temp->next = temp->next->next; Node* dumm=temp->next; delete (dumm);
5. temp->next = temp->next->next; temp->next=NULL; delete (temp->next);포인터라는거 진짜 상당히 헷갈리지 않나요? 문제가 잘못되었다고 논리적으로 항변하셔도 됩니다 ㅋㅋㅋ
-
-
Temp next부터 갈아치우는 솔루션은 unreferenced object 때문에 전부 틀려서 가능한 답이 1번뿐인데 이건 null check도 안하네 ㅋㅋ 이건 누구 숙제인건지 아니면 c++ 배우는게 진짜로 재밌어서 이런걸 올리는건지 궁금하군요
-
죄송하지만 pointer와 linked list에 대해 최소한의 공부라도 먼저 하시고 질문하시면 좋겠습니다.
계속해서 이런 질문 하시는 것을 보면 이제는 혹시 낚시글이 아닐까 싶을 생각이 들 정도에요. -
위에 뎃글님
실력이 그렇게 좋은데 전혀 논리다운 논리가 한마디도 없나요? 잘난체 하시려면 실력을 증명해보세요 간단한 퀴즈정도에 문제의 코어 이슈가 뭔지 지적할 정도는 돼셔야죠. 난 저런 기본문제다루기엔 실력이 너무 좋아 이런생각이시면 그냥 넘어가시구요. 저 간단한 퀴즈에는 적어도 3가지 기본적인 이슈가 있어요. 아마 1번이 답일꺼 같다라는 정도는 좀 공부했으면 다 생각할수는 있겠죠-
제가 지난번 댓글에서도 공부 좀 먼저 하시라고 친절하게 링크까지 달아 드렸었는데 이를 무시하시고 계속 이런 질문을 하시네요.
정말 모르셔서 질문하시는 건가요? 아니면 그냥 게시판 이용자들 낚으시려고 그러시는 건가요?
그리고 여기는 US Life게시판이지 이런 코딩 질문 하는 곳이 아닙니다.-
보기 싫음 그냥 패스하길.
눈에 보인다고 다 댓글달고 관심보여야 한다고 생각하는것도 일종의 정신 질환입니다. 깨끗한 손도 계속씻어야 하는 일종의 편집증같은거죠. 앞으로는 불필요한 댓글을 달지 않겠다는 절제력을 기르세요. 아무데나 참새방앗간처럼 기웃대지말고요. 방앗간 볍씨들이 님같은 참새들을 위한건 아닌데 참새들이 착각하죠. 님같은 댓글 환영하지도 않지만 앞으로는 나도 그냥 무시할게요.-
제 댓글도 보기 싫음 그냥 패스하길.
눈에 댓글이 보인다고 거기에 또 댓글달고 관심보여야 한다고 생각하는것도 일종의 정신 질환입니다. 깨끗한 손도 계속씻어야 하는 일종의 편집증같은거죠. 앞으로는 불필요한 댓글을 달지 않겠다는 절제력을 기르세요. 아무데나 참새방앗간처럼 기웃대지말고요. 방앗간 볍씨들이 님같은 참새들을 위한건 아닌데 참새들이 착각하죠. 님같은 댓글 환영하지도 않지만 앞으로는 나도 그냥 무시할게요.-
wl 을 내가 기억할것도 아니고…앞으론 댓글 달지 마시고 그냥 강호 고수가 나타날지 안나타날지 사이드 관중석에서 다른 구경꾼들과 함께 구경만 하시기를…본인이 고수도 아니면서 고수인척 칼도 안가져와서 알짱거리면서 개쪽당하지 말고. 뭐 근데 난 초등생이라도 배울자세가 되어있는 겸손한 자세와 정정당당한 경합과 시합이라면 언제라도 환영함. 그래야 초등학생도 성장할거 아닌가 아무리 초등학생한테서도 배울점이 있을수도 있는거고. 이런 주최측을 비난만 하는 깔짝거리는 비겁한 경합 말고.
-
-
-
-
-
학교숙제? ㅋㅋㅋ
-
어떤 학교 교수가 저런 허접하고 정제되지 않은 퀴즈를 숙제로 내겠어요?
허접하지만 기본 개념을 생각해보기엔 나쁘지 않은 퀴즈.
-
-
비슷한 입장의 사람들과 얘기하고 싶은 것 같은데, 여기는 별로 적합하지 않아 보이는군요.
-
기본개념을 제대로 확실히 아는 고수가 이 싸이트에 별로 없는 거 아닐까요?
사실 “이 거 코드 뭐가 에러인지 봐주세요” 이런 류의 질문이 대답하기에도 쉽고 아주 편한 질문이죠. 그런데 기본 개념에 관한건 본인이 머리에 확실한 개념이 설정되야 짧게 명료하게 표현이 가능하죠. 초등학생이 처음배우는 항등원이나 역원 그런 개념들 초등학생들이 제대로 이해하고 덧셈뺄셈 하는건 아니죠. 이 싸이트에는 그런 고수가 없는거 같아요. 깔짝거리며 짧은 지식으로 내용자체는 못다루면서 아는체만 하려는 사람만 많은듯. 내 퀴즈에는 내 개념을 확실히 하려는 목적과 이 싸이트의 풀에대한 수준이 어느정도인가 가늠하고자하는 목적도 있어요. 그러나 아직 내 판단은 유보중이니, 만약 강호에 내로라하는 고수가 이 싸이트에 있다면 언제든지 참여해서 한번씩 실력을 보여주세요. 퀴즈 수준이 낮고 개념수준이 낮다고 해서 칼솜씨까지 낮아야 하는 건 아니죠. 파리한마리 죽이는 허접한 퀴즈에도 고수의 칼날은 그 수준이 드러나고 마는법. 강호의 고수를 찾는 서치는 앞으로 계속될것. 짜~잔. 이러다 내가 그 강호의 유일한 최고 고수가 되어버릴거같은 예감. ㅋㅋ-
여기서 괜히 분란 일으키지 마시고, 코딩 질문은 코딩 전문 웹사이트에서 가서 해주세요
https://stackoverflow.com/-
강호의 “진정한” 고수를 찾는 서치는 앞으로 계속될것. 짜~잔.
ㅋㅋㅋ 다시 읽어보세요. 하긴 세상사가 다 비슷한것이….진정한 고수는 일부러 숨어서 안나타나고 고수인척 하는 가짜들만 자기들이 판을 다 소유해서 마켓을 컨트롤하고 싶어하는거 같아요. 그래야 가짜 검술학원이라도 운영이 되니까 그런가…어디서 많이 본 영화 플롯같다.
-
-
-
-
https://black7375.tistory.com/1
<각종 커뮤니티에서 프로그래밍 질문하는 법>
가끔 모르는 정보가 있다보면 누군가에게 물어봐야 될 때가 있다.
그런데 주변에 잘 아는 사람이 없다면 커뮤니티에 물어볼 수 밖에 없다.
이 글에서는 어떻게 해야 커뮤니티에서 질문을 잘하는지,
내 경험에 비추어 설명하고자 한다.
그 중 간단하게 5가지로 추렸다.0. 최대한 문제의 답에 접근해보자.
전공책이나 구글, 빙등 검색엔진을 이용하여 해결 할 수 있는지
찾는 것은 기본 중의 기본!
여러분이 커뮤니티에 질문하기 전에 선행되어야 할 것이 있다.
바로 문제를 해결하기 위해 노력하는 것이다.
충분히 할 수 있는 것에 대해 질문하면, 실력이 늘지 않는다.
앞으로 프로그래밍을 하려면 검색하는 습관을 들여야한다.
(물어보면 검색해보라는 말을 많~이 들을 것이다.)
책에서 나오지 않는 실전적인 문제들은 인터넷에 잘 나와있고, 회사에 가서도 계속 상사에게 물어볼 수는 없는 노릇이니 검색을 하는 습관을 잘 들이는 것은 좋다고 생각한다.
특히 프로그램을 구현하는 것은 아주 어려운 것이 아닌 이상 인터넷에 나와있기 때문에 검색하도록 하자.
너무 초보적인 질문을 하면 커뮤니티에서도 답변해주지 않는 경우가 많다.
노오오오력합시다!!1. 커뮤니티를 정한다.
카페든, IT 커뮤니티이든, 프로그래밍 커뮤니티이든 하여튼 정합니다.
여러분이 영어를 잘한다면 https://stackoverflow.com/ 라는 곳을 이용하는 것을 추천한다.
빠른 시간내에 답변이 정성껏 올라옵니다.2. 기본적인 형식을 갖추기.
“*ㅂ 이거 어떻게 해?”
“여기에서 뭐해야되냐?”
DC Inside 같이 반말을 쓰는게 자유로운 사이트가 아닌 이상 일단 비속어를 사용하거나 상대방의 신경을 거스르는 말은 하지 말자. 단순하게 신고를 먹는 거나 조롱하는부터 퇴출 당하는 것까지 제제는 다양하다.
설사 아무 답변을 안해주도라도.
(애초에 답변을 해주는 것은 선의로 하는 행동임을 명심 또 명심!.)
이상한 말을 하면 답변을 해주려고 했어도 안해주고,
가는말이 고우면 오는 말도 고운게 사람의 마음이니,
설사 DC라 할지라도 예의 바르게 물어본다면 답변해줄 확률이 높아질 것이다.3. 구체적으로 설명하기 && 열정을 보여주기.
밑도 끝도 없이,
“이거 어떻게 해요?”
라고 물어본다면 보는 사람들은 노력이나 성의를 보이지 않고 정보를 뜯어가려고 하는 이른바 ‘과.제.충’이라 생각하게 된다.
(이런 사람들이 답변받고 질삭하고 튀는 경우가 빈번하다.)
그렇다면 오해받지 않으면서 질문을 하는 방법은 무엇일까?
내가 경험해본 바로는,
첫번째로 자신이 구현하려고 하는 것이 무엇인지 명확하게 알려주고(What)
두번째로 구현을 하려고 할 때 어떻게 했는지를 말하며(How)
마지막으로 모든 것을 해주라 하지 말고 어떠한 방향으로 가야하는지, 방법을 물어야 한다.(How to)
답변해줄 사람은
질문자가 무엇을 원하는지 알아야 하고,
어떠한 방법을 시도했는지 궁금해할 것이며,
자신이 모든 것을 해주기는 귀찮고 바쁠 사람들이 감사인사 하나 받자고 호구가 되려하지 않을 것이다.
(그래야 빠르고 정확하게 답변하기가 쉽다.)
구체적으로 어떻게 생각했고 무엇을 해봤는지 기술하면서
모든 것을 해주길 바라지 말고 어떤 방법을 써봐야 하는지 물어보자.
돈받고 과제를 해달라는 사람들도 있는데 가끔 돈받고 해주는 사람도 있기는 하지만, 대부분 조롱을 받기 일수.4. 간결히 설명하기.
구체적으로 설명하기가 바로 위에 나와서 혼동이 되는 사람이 있을 것이다.
그러나 구체적으로 설명하는 것과 알아듣기 쉽게(간결하게) 설명하는 것은 다른 것이다.
질문을 보기좋고 인식하기 쉽게끔
되도록 지엽적인 부분으로 문제를 잘라 설명하도록 하자.5. 소스코드 첨부하기.
소스코드도 없이 물어본다면 답변을 안해줄 가능성이 역시 커진다.
당신이 무엇을 어떻게 했는지 상대방이 어떻게 알것인가?
아무리 구체적으로 설명했더라도 실제로 보아야 알 수 있는 부분이 있다.+. 감사 인사하기.
답변을 잘 받았다면 감사인사를 하자.
기분이 좋아서 다음에 질문한 것을 볼 때 더 열심히 답변해주거나.
꿀팁을 줄수도 있다. -
이런저런 오류가능성을 접어두면, 1번이 그나마 답입니다.
temp->next를 변경하기 전에, 삭제할 temp->next를 backup했어야합니다.친절은 의무가 아닙니다.
이런류의 커뮤니티에 질문을 할때는 다소 불친절하거나 감정을 건드리는 답변을 어느정도 감수해야합니다. 이런상황은 여느 인간관계에서도 발생합니다.
이런것에 일일이 감정적으로 대응하면, 본인 인생만 피곤해집니다.-
알겠습니다. 빌런 처럼 구는 사람들은 무시하겠습니다.
저도 1번이 확실한 답인건 알아요. 물론 널체크나 사소한것들이 있지만…근데 문제는 원글의 3번같은 경우인데….사실 1번의 경우처럼 포인터를 두개를 쓰지 않고, 1개만 쓰고도 삭제 타겟 노드를 리스트에서 링크를 끊어 고립시키는 목적을 이루어낼수는 있는데, 포인터 2개를 쓸때는 메모리 리크방지를 위해 메모리 삭제 delet temp; 쓰는 방법이 명확한데, 포인터를 1개만 쓰는 경우 노드의 메모리 삭제 delete 노드를 하는 경우가 생각대로 되지 않아요. 예를 들어 delete(node->next); 라는 문장이 일리걸한 것인지..논리적인 모순이 생기는건지….이건 아래 예제와도 연관이 있어요. 아래 예제에서도 포인터 1개만 이용하고서 메모리리크가 되지 않도록 고립된 노드메모리를 딜리트 해버려야 하는데…생각대로 되질 않네요.
void deleteNode(Node* node) { if (node == nullptr) return; if (node->next == nullptr) { // 노드가 한개던지, 마지막 노드일때? 일단 이 경우는 여기서는 고려하지 말자 } else { node->data = node->next->data; node->next = node->next->next; // 사실 여기까지는 아무문제 없어요. 그런데 여기까지만 보면 node 는 링크만 끊은것이지 메모리가 해제된건 아니어서 메모리 리크가 생기지 않나요? 그래서 아래처럼 딜리트까지 시켜야 할거 같은데 ... node = node->next; // 노드 메모리삭제하기전에 포인터 이동 delete node; // ???? 포인터 1개만 쓰면서 노드메모리를 삭제할려면? 올드 노드가 필요한데... } }아래는 테스트할 경우
#include <bits/stdc++.h> using namespace std; /* Link list node */ class Node { public: int data; Node* next; }; 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* head) { Node* temp = head; while (temp != NULL) { cout << temp->data << " "; temp = temp->next; } } void deleteNode(Node* node) { if (node == nullptr) return; if (node->next == nullptr) { // 노드가 한개던지, 마지막 노드일때? } else { node->data = node->next->data; node->next = node->next->next; node = node->next; delete node; // ???? wrong } } /* Driver code*/ int main() { Node* head = NULL; // Use push() to construct below list 1->12->1->4->1 //push(&head, 1); //push(&head, 4); push(&head, 1); push(&head, 12); push(&head, 1); cout << "Before deleting \n"; printList(head); //deleteNode(head); //deleteNode(head); deleteNode(head->next); cout << "\nAfter deleting \n"; printList(head); return 0; }경우 1) 위의 테스트 경우 아웃풋
Before deleting
1 12 1
After deleting
1 1경우 2) 그런데 아래처럼 메인함수를 테스트해보면
deleteNode(head);
deleteNode(head);
//deleteNode(head->next);아웃풋이 아래처럼 나옵니다.
Before deleting 1 12 1 After deleting 0 0 0 0 0 0.....그런데
delete node;
를 코멘트해버리면
결과는 또 잘 나옵니다.타겟 노드를 리스트에서 링크를 끊었으니 결과는 잘 나오는게 당연한데….문제는, 내 생각에 이 노드가 메모리 리크의 문제를 일으키지 않게 하기 위해 delete node; 를 해버려야 하는데…포인터를 1개만 쓰면서 그게 가능한지 모르겠어요. 포인터를 1개가 아니라 2개를 도입해서 원글의 1번의 경우처럼 쓰면, 이 문제는 없어지는데….포인터 1개만 쓰면서 원하는 노드 메모리를 딜리트 시키는 방법이 있는건지…. 그게 사실 원글의 3번에서 시도해보려했던 경우와 비슷한데….하긴 거기서도 더미 포인터를 도입했지만..
-
-
문제를 간략히 정리하자면, 사실 이건 리트코드 #237과 관련있는데…
크게 두가지 개략적 솔루션을 생각해볼수 있어요.솔루션 1: void deleteNode(ListNode* node) { ListNode *temp = node->next; *node = *temp; temp->next = NULL; delete temp; } 솔루션 2: ==> 결국 메모리삭제도 요구되면 잘못된 솔루션? . void deleteNode(ListNode* node) { // 메모리 리크 문제 없나? node->val = node->next->val; node->next = node->next->next; }솔루션2는 포인터를 1개만 쓴경우죠. 이 경우, 메모리리크 문제가 생기는거 같은데…솔루션1의 경우 템프처럼 node 말고 다른 포인터를 꼭 도입해야만 메모리를 삭제시킬수 있을까 그냥 메모리리크 문제 해결하는 방법이 없는가가 문제의 모티브입니다. 보통 여분의 포인터 도입 않하고도 문제가 해결할수있는 방법이 많은데 메모리리크를 고려해야 한다면 여분의 포인터를 도입하는게 정석일까….이런 생각….
-
구경꾼들 … 싱겁다고 다 떠나갔구만..ㅋㅋ 그래도 꽁짜 관람.
-
3. temp->next = temp->next->next; Node* dumm=temp->next; dumm=NULL; delete (dumm);
=>
Node* dumm=temp->next->next; delete(temp->next); temp->next = dumm;-
or
Node* dumm=temp->next; temp->next = temp->next->next; delete(dumm);
나머지 패턴들은 다 이해가 가는데,
오리지날 3에는 어떤일이 일어나고 있는지 진짜 헷갈려 ㅋㅋ (주소저장하는 방이 이미 넥스트넥스트 메모리주소로 엎데이트되어버려서 넥스트 주소를 저장할 기회를 이미 놓쳐버렸다? … 그러면 그뒤에 두번째 라인으로 오는 더미 포인터가 저장하게 되는 주소는 원하던 넥스트주소가 아니라 의도하지 않은 넥스트넥스트 주소가 되어버린다? 아이고 이 간단한거 이해하기가 왜이럽게 힘드냐 ㅋㅋㅋ 결국 내가 생각했던것처럼 더미포인터가 넥스트메모리주소에 가있었던게 아니라 넥스트넥스트 메모리주소에 가있었던 거였나보군. 그러니 엉뚱한 메모리를 지워버린거였어..)정리하자면:
1. 노드의 메모리삭제하려면, 항상 여분의 더미 포인터를 하나 더 정의해주어야 한다.
2. 더미 포인터에 무엇보다 먼저 메모리 삭제할 노드의 올드메모리 주소를 먼저 저장해두어야 한다. 순서가 잘못되면 엉뚱한 메모리가 지워진다.-
3. 사실 또 한가지 주목해야 하는것은 예를 들어 ptr 는 주소값도 가지고 메모리주소를 포인트하는 포인터이지만, ptr->next 처럼 넥스트가 꼬리처럼 붙어다니는것들은 실제로 존재하는 포인터가 아니므로 포인터처럼 취급하지 말라는 사실, 결국 delete(ptr->next) 라고 쓰는게 틀린건 아니지만, 이게 혼동을 야기하는 근원이 되므로(적어도 나한테는 이게 혼동의 근원이 되었다) 가능하면 이런 방식으로 넥스트를 꼬리처럼 달고있는것들을 딜리트와 같이 쓰지 말란 말이다. 이게 뭔소린고 하면, Node *ptr; 나 Node *dummy; 는 가능하지만, Node* ptr->next; 라고는 선언하지 않는 이유이다. 즉, 엄밀히 말하면 ptr->next 는 포인터가 아니다. delete(A) 는 A가 실제적인 포인터이든지 아니든지간에 어쨌든 “주소”만 가지고 있으면 실행이 된다. 물론 c++처럼 메모리리크를 걱정해야 할 필요가 없는 랭귀지에서는 이런거 걱정할필요없으니 안따져도 될거같지만…
-
-
-
-
-