Skip to content

Instantly share code, notes, and snippets.

@blood72
Created May 30, 2019 06:30
Show Gist options
  • Save blood72/b73491670fe90a1b289236ce1d45a6e9 to your computer and use it in GitHub Desktop.
Save blood72/b73491670fe90a1b289236ce1d45a6e9 to your computer and use it in GitHub Desktop.
학창 시절에 만든 C언어 구조체 연결리스트 (int형 / char형 주석구분)
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996) //scanf 에러문 무시
// #define BUF_SIZE 100 // char 형태 데이터
// #define NAME_SIZE 20 // char 형태 데이터
typedef struct Node{
int data; // int 형태 데이터
// char data[NAME_SIZE + BUF_SIZE]; // char 형태 데이터
struct Node *link;
} Node;
void display(Node **head) // 입력과정을 검산하는 함수
{
Node *p = (*head)->link; // 헤드노드 이후부터 출력하기 위한 포인터
while (p != NULL) // 연결리스트 끝까지 출력
{
printf("%d->", p->data);
p = p->link;
}
if ((*head)->link == NULL) // 헤드노드가 NULL이면
printf("노드가 비어있습니다.");
printf("\n");
}
void appendNode(Node **pointer, int data)
{ // 새로운 노드를 리스트에 연결시키는 함수
// 첫번째 전달인자 Node * 다음에 전달되는 데이터 (int)를 연결시킴.
// 특정노드를 가리키는 포인터와 새 노드에 넣을 값을 인자로 받는다.
Node *p = *pointer; // 연결시킬 기준노드
Node *new_node; // 새롭게 추가될 노드
new_node = (Node *)malloc(sizeof(Node));
new_node->data = data; // int 형태
// strcpy(new_node->data, data); // char 형태
// new_node를 p와 p->link 사이에 삽입한다. (p->link==NULL 포함)
new_node->link = p->link;
p->link = new_node;
}
void createNode(Node **head)
{ // 사용자가 원하는 노드 수 만큼 단순연결리스트를 만드는 함수.
// main함수에서 호출하며 리스트 헤드포인터의 포인터를 전달인자로 사용
// 노드를 리스트에 연결할 때 appendNode함수를 호출하여 사용
Node *p = *head;
int value = 0; // int 형태
// char value[NAME_SIZE + BUF_SIZE]; // char 형태
char cmd[12] = { 'y' }; // 초기값을 y로 주어 자동으로 반복문 진입
while (cmd[0] != 'n')
{
printf("데이터를 입력하세요 : ");
scanf("%d", &value);
appendNode(&p, value); // 노드 값 생성 및 연결
fflush(stdin); // BUFFER표준입력영역정리
printf("계속 진행하시겠습니까?(yes/no) : ");
scanf("%s", &cmd);
p = p->link; // 포인터를 1칸 전진시킴
display(head);
}
}
Node *searchNode(Node **head, int value)
{ // 함수의 두번째 전달인자를 리스트에서 찾아 그 데이터의 이전 포인터를 리턴하고,
// 찾은 데이터를 가리키는 포인터를 첫번째 전달인자에 저장하는 함수.
// 값을 찾으면 가장 좌측부터 반환함.
Node *p = (*head)->link;
Node *prev = *head;
int pos = 1; // 검색된 노드의 위치변수
display(head);
// 데이터를 찾으면 빠져나옴.
while ((p->link != NULL) && (p->data != value)) // int 형태
// while ((p->link != NULL) && (strcmp(p->data, value))) // char 형태
{
prev = p;
p = p->link;
pos++;
}
if ((p->data == value)) // int 형태
// if (!strcmp(p->data, value)) // char 형태
{
printf("찾는 값(%d)은 %d번째에 있습니다.\n", p->data, pos);
return prev;
}
else
{
printf("찾는 값이 존재하지 않습니다. (검색한 값 : %d)\n", value);
return NULL;
}
}
void insertNode(Node **head)
{ // 삽입할 데이터와 위치를 입력받고 searchNode 함수를 이용하여 위치를 찾고
// 새로운 노드를 appendNode 함수를 이용하여 리스트에 연결
int value; // int 형태
// char value[NAME_SIZE + BUF_SIZE]; // char 형태
Node *p;
printf("삽입할 위치의 데이터를 입력하세요 : ");
scanf("%d", &value);
printf("기존 : ");
p = searchNode(head, value); // 노드검색함수를 호출해 p값에 저장한다.
if (p == NULL) // 이 때, p는 삽입할 위치의 이전 데이터를 가리킨다.
printf("찾는 값이 존재하지 않아 삽입할 수 없습니다.\n");
else
{ // p != NULL일 때 삽입할 데이터위치(p->link)를 주고 appendNode호출
fflush(stdin); //BUFFER표준입력영역정리
printf("삽입할 데이터를 입력하세요 : ");
scanf("%d", &value);
appendNode(&(p->link), value); // 노드 값 생성 및 연결
}
printf("결과 : ");
display(head);
}
void deleteNode(Node **head)
{ // searchNode함수를 이용하여 원하는 원소를 찾고 삭제하는 함수
int value; // int 형태
// char value[NAME_SIZE + BUF_SIZE]; // char 형태
Node *p;
Node *pnext;
printf("삭제할 데이터를 입력하세요 : ");
scanf("%d", &value);
printf("기존 : ");
p = searchNode(head, value); // 노드검색함수를 호출해 p값에 저장한다.
if (p == NULL) // 이 때, p는 삽입할 위치의 이전 데이터를 가리킨다.
printf("찾는 값이 존재하지 않아 제거할 수 없습니다.\n");
else
{ // p != NULL일 때 삭제할 데이터영역(pnext)을 삭제
pnext = p->link;
p->link = pnext->link;
free(pnext);
}
printf("결과 : ");
display(head);
}
/* - 기본 원리 -
head_node는 searchNode함수에서 쓰이는 포인터 prev를 제대로 반환하기 위해 삽입했습니다.
헤드포인터가 head_node를 가리키고 있지만 실제 운영은 헤드노드부터 시작합니다. */
int main(void)
{
int command; // 스위치 조건문을 움직일 변수
int value; // int 형태. 데이터 입력받을 변수
// char value[NAME_SIZE + BUF_SIZE]; // char 형태.
Node *head_node = (Node *)malloc(sizeof(Node)); // 헤드노드
Node *head = head_node; // ※헤드포인터는 헤드노드를 가리킨다.
head_node->link = NULL;
while (1)
{
fflush(stdin); //BUFFER표준입력영역정리
puts("\n0 : 종료, 1 : 생성, 2 : 검색, 3 : 삽입, 4 : 삭제");
printf("위의 명령 중 하나를 입력하세요 : ");
scanf("%d", &command);
switch (command)
{
case 1: // 노드를 생성한다.
if (head->link == NULL) //NULL일 때만 진입을 허용한다.
createNode(&head); //노드생성함수 호출
else printf("이미 연결리스트가 존재합니다!\n");//"헤드포인터는 NULL이 아닙니다.");
break;
case 2: // 노드에 들어있는 값을 조사하여 위치를 출력한다.
if (head->link != NULL) //연결리스트가 존재할 때만 진입한다.
{
printf("검색하고 싶은 값을 입력하세요 : ");
scanf("%d", &value);
printf("출력 : ");
searchNode(&head, value); //노드검색함수 호출
}
else printf("연결리스트가 존재하지 않습니다!\n");
break;
case 3: // 기존 데이터를 검색하고 해당하는 노드 뒤에 삽입할 데이터를 입력받고 연결시킨다.
if (head->link != NULL) //연결리스트가 존재할 때만 진입한다.
insertNode(&head); //노드삽입함수 호출
else printf("연결리스트가 존재하지 않습니다!\n");
break;
case 4: // 데이터를 검색해 해당하는 값을 가진 가장 좌측의 노드를 삭제한다.
if (head->link != NULL) //연결리스트가 존재할 때만 진입한다.
deleteNode(&head); //노드삭제함수 호출
else printf("연결리스트가 존재하지 않습니다!\n");
break;
case 0:
return 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment