Tech Blog/C and C++

C언어 - 연결리스트 만들기 [실습 포함]

EXPRESSIONS HAVE POWER 2021. 6. 10. 15:15

기초버전

#include <stdio.h>
#include <stdlib.h>

struct NODE {
    struct NODE *next;
    int data;
};

int main()
{
    struct NODE *head = malloc(sizeof(struct NODE));

    struct NODE *node1 = malloc(sizeof(struct NODE));

    head->next = node1;
    node1->data = 10;

    struct NODE *node2 = malloc(sizeof(struct NODE));
    node1->next = node2;
    node2->data = 20;

    node2->next =NULL;

    struct NODE *curr =head ->next;
    while(curr != NULL)
    {
        printf("%d\n", curr->data);
        curr = curr->next;
    }

    free(node2);
    free(node1);
    free(head);
}

실행결과

10
20

head : 단일 연결리스트 기준점(데이터 저장x)

node : 실제 데이터 저장 

head ->  node1 -> node2 -> null

 

연결리스트에서 노드를 추가하는 규칙

 

1. 노드에 메모리 할당

2. next 멤버에 다음 노드의 메모리 주소 저장

3. data 멤버에 데이터 저장

4. 마지막 노드라면 next 맴버에 NULL 저장 

 

번외편 (자기 참조 구조구분 = 자체 참조 구조 구분)

#include <stdio.h>

static struct S1 {
    char *s;
    int i;
    struct S1 *s1p;
};

main(){
    static struct S1 a[ ]= {
        {"abcd", 1, a+1},
        {"efgh, 2, a+2"},
        {"ijkl", 3, a}
    };
    struct S1 *p = a;
    int i;

    printf("%s %s %s\n", a[0].s, p->s,a[2].s1p->s);

    for(i = 0; i<2; i++){
        printf("%d\n", --a[i].i);
        printf("%d\n", ++a[i].s[3]);
    }
    printf("%s %s %s\n", ++(p->s), a[(++p)->i].s, a[--(p->s1p->i)].s);
}

번외편 2 

#include <stdio.h>

main()
{
	static struct S1 {
		char c[4], * s;
	} s1 = { "abc","def" };

	static struct S2 {
		char* cp;
		struct S1 ss1;
	} s2 = { "ghi",{"jkl","mno"} };

	printf("%c %c\n", s1.c[0], *s1.s);
	printf("%s %s\n", s1.c, s1.s); 
	printf("%s %s\n", s2.cp, s2.ss1.s);
	printf("%s %s\n", ++s2.cp, ++s2.ss1.s);
}

실행결과 

a d
abc def
ghi mno
hi no

실습 - invert(root) 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct node {
    char* name;
    struct node* link;
};
int getname(char*);
struct node* addlist(struct node*, char*);
char* namecopy(char*);
void listprint(struct node*);
struct node* invert(struct node* lead);
//____________________________________    invert 함수 선언 할 것

int main()
{
    struct node* root;
    char name[80];
    root = NULL;
    while (getname(name) != EOF)
        root = addlist(root, name);
    listprint(root);

    root = invert(root);   // 함수 콜
    printf("------ - invert------\n");
    listprint(root);         //역순화된 연결 리스트 출력

    return  0;
}
int getname(char* pname)
{
    int i = 0;   char c;
    while (((c = getchar()) != '\n') && c != EOF)
        *(pname + i++) = c;
    if (c == '\n')
        *(pname + i) = '\0';
    if (c == EOF)
        *pname = EOF;
    return  *pname;
}

struct node* addlist(struct node* p, char* w)
{
    if (p == NULL) {
        p = (struct node*)malloc(sizeof(struct node));
        p->name = namecopy(w);
        p->link = NULL;
    }
    else
        p->link = addlist(p->link, w);
    return  p;
}

char* namecopy(char* s)
{
    char* p;  int i = 0;
    p = (char*)malloc(strlen(s) + 1);
    while ((*(p + i) = *(s + i)) != '\0')   i++;
    return  p;
}

void listprint(struct node* p)
{
    while (p != NULL) {
        printf("%s\n", p->name);
        p = p->link;
    }
}

struct node* invert(struct node* lead)
{
    struct node* middle, * tail;
    middle = NULL;
    while (lead != NULL)
    {
        tail = middle;
        middle = lead;
        lead = lead->link;
        middle->link = tail;
    }
    return middle;
}

실행결과

입력 값
asdf
qwer
zxcv
window - ctrl(^) + z
mac - control(^) + d 

출력 값

asdf
qwer
zxcv
------ - invert------
zxcv
qwer
asdf