구조체와 포인터를 이용하여 Linked List를 만드는 예시이다.
우선 구조체는 데이터와 다음구조체의 주소를 가지는 포인터를 갖는다.
1 2 3 4 | struct Data { int value; Data* pNext; }; | cs |
1. 입력
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | Data* pHead = NULL; if (menu == 1) { int input = 0; cout << "입력할 값은? : "; cin >> input; //새로운 구조체를 만들어 그 안에 값을 넣는다. pNext는 처음에는 널값으로 생성. Data* pNewData = new Data; pNewData->value = input; pNewData->pNext = NULL; // 헤드가 비어있다면 새로운 값을 헤더로 if (pHead == NULL) pHead = pNewData; else { // 아니라면 temp에 헤드를 넣어준다. Data* temp = pHead; // 이후 헤드부터 Next가 존재하면 계속 타고가서 마지막까지감 while (temp->pNext != NULL) { temp = temp->pNext; } // 마지막에서 pNext에 새로만든 구조체(pNewData)주소를 연결해준다. temp->pNext = pNewData; } cout << "값이 입력되었습니다. \n\n"; } | cs |
주석을 다 달아놨지만. 우선 Head가 존재한다. Head는 Linked List의 시작점을 뜻한다.
입력은 새로운 구조체를 생성해 그 안에 입력받은 value값을 넣어주고 pNext는 NULL로 생성한다.
그리고 Head가 비어있다면 새로운값을 연결해주고(주소를 넣어줌. 포인터니까)
Head에 값이 있다면 pNext를 따라 계속 다음주소로 넘어가고 그 다음주소로 넘어가고..
마지막주소에 도달하면 그다음값으로(pNext) 새로운값(pNewData)의 주소를 넣어주면 리스트가 연결될 것이다.
temp는 탐색하기 위한 변수라고 생각하면 이해에 도움이 될 것이다.
그림으로 그리자면 이런식이 될 것이다.
2. 출력
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | else if (menu == 2) { Data* temp = pHead; if (pHead == NULL) cout << "입력된 값이 없습니다. \n\n"; else { // Head부터 반복하면서 value값을 출력 while (temp->pNext != NULL) { cout << temp->value << " "; temp = temp->pNext; } // 마지막값의 value값도 출력 cout << temp->value << "\n\n"; } } | cs |
입력과 마찬가지로 temp를 이용하여 Head부터 쭉 타고가면서 value값을 순서대로 출력해준다.
즉 입력받은 순서대로 모든 값이 출력 될 것.
3. 삽입
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | else if (menu == 3) { int input = 0; cout << "삽입할 값은? : "; cin >> input; // 새로운 데이터를 생성 Data* pNewData = new Data; pNewData->value = input; pNewData->pNext = NULL; // Head가 비어있다면(데이터가 없다면) Head에 주소를 넣어줌 if (pHead == NULL) { pHead = pNewData; cout << "저장된 값이 없어 첫번째값으로 입력됩니다. \n\n"; } else { int num = 0; cout << "몇번째에 삽입하시겠습니까? : "; cin >> num; // 1번째에 삽입하면 새로운데이터가 Head가 되야함 if (num == 1) { pNewData->pNext = pHead; pHead = pNewData; } // 아니라면 탐색하면서 중간에 삽입 else { Data* temp = pHead; // 시작이 헤드(1)이므로 2번째칸에 넣고싶으면 1뒤에 넣으면됨(1~2사이니까 결국 1뒤) // 그렇기 때문에 2를 입력받으면 head 바로 뒤에 삽입하면 되므로 n-2 for (int i = 0; i < num - 2; i++) { temp = temp->pNext; } // 기존 next값을 새값에 넣어주고 기존값의 next를 새값으로 바꿈 pNewData->pNext = temp->pNext; temp->pNext = pNewData; } cout << "입력값이 삽입되었습니다 \n\n"; } } | cs |
삽입은 입력과 마찬가지로 새 데이터를 생성하고 Head가 비어있다면 입력과 마찬가지로 Head를 새값으로.
아니면 중간에 데이터를 연결해준다.
중간에 데이터를 삽입하려면 위의 그림처럼 next의 값을 newData의 next값에 넣어주고(빨간색 화살표)
기존데이터의 next에 newData의 주소를 넣어주면 가운데에 삽입이 될 것이다. (주황색 화살표)
그렇게되면 녹색화살표와 같은 순서대로 List가 연결된다.
4. 삭제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | else if (menu == 4) { // t1 = 현재주소값, t2 = 삭제를 위해 다음으로 먼저 넘어갈값 Data* t1 = pHead; Data* t2 = pHead; if (pHead == NULL) cout << "입력된 값이 없습니다. \n\n"; else { int deletedata; cout << "삭제할 값을 입력하세요 : "; cin >> deletedata; // Head를 삭제하면 Head를 다음으로 넘겨줌 if (pHead->value == deletedata) { pHead = pHead->pNext; delete t1; } else { // 마지막까지 검색 while (t2->pNext != NULL) { // t2를 앞으로 보내 삭제할 값이면 데이터를 연결하고 삭제 t2 = t1->pNext; if (t2->value == deletedata) { t1->pNext = t2->pNext; delete t2; break; } // 삭제할 값이 아니면 t1도 따라서 앞으로 넘어옴 else t1 = t1->pNext; } } if (t2->pNext == NULL) cout << "해당 값을 찾지 못하였습니다. \n\n"; else cout << "해당 값을 삭제하였습니다. \n\n"; } } | cs |
삭제는 검색할 때에 temp가 2개가 필요하다.
중간에 찾아버리고 삭제하면 List가 끊기기때문에 앞이랑 뒤를 연결해야 하므로 하나씩 따로 움직인다.
만약 삭제할 값이 Head면 삭제할 시 Head가 없어지므로 Head를 다음값(next)로 넘겨주고 데이터를 삭제.
아닌경우에는 t2가 먼저 넘어가서 삭제할값인지 확인하고,
맞다면 t1의 next에 t2의 next를 넣어 다음값으로 연결해 준 뒤 t2를 삭제하면 된다.
(이제 그림없어도 이해하실듯)
5. 종료
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Data* t1 = pHead; Data* t2 = pHead; if (pHead != NULL) { // 한칸 넘어가고 이전거 삭제 반복 if (t2->pNext != NULL) { t2 = t1->pNext; delete t1; t1 = t2; } // 마지막도 delete t2; } | cs |
우리는 구조체를 동적할당했기 때문에 프로그램이 종료되면 할당한 메모리를 다시 돌려주고 종료한다.
'프로그래밍 공부 > C++' 카테고리의 다른 글
동물 스무고개(?) (Tree연습 예제) (0) | 2018.03.21 |
---|---|
Tree (재귀함수 이용) (0) | 2018.03.21 |
구조체(struct) (0) | 2018.03.21 |
문자열 길이구하기, 복사하기, 추가하기 (포인터 이용) (0) | 2018.03.12 |
정적할당과 동적할당 (0) | 2018.03.12 |