728x90

배열과 연결리스트 두 자료구조 모두 데이터를 나열한다는 점에서 비슷하게 생각할수있습니다.

 

그러나 두 자료구조는 확실한 차이가 있습니다.

 

배열의 경우 사용이 매우 간단하다는 장점이 있는 반면, 배열의 가장 큰 단점은 크기가 고정된다는 점이다.

 

프로그램이 실행이 되고 나면 배열의 크기를 줄이거나 늘릴수없습니다. 

 

배열의 크기를 잘못 예측하여 실제보다 작은 크기로 선언할경우 저장공간이 부족하게되고 너무 큰 크기로 배열을 선언하면 메모리 저장공간을 낭비하게 됩니다

 

배열과 같이 프로그램이 실행전 메모르 크기가 결정되는 메모리할당 방법을 정적메모리 할당이라 합니다.

 

이러한 단점들을 보완하는 자료구조가 대표적으로 연결리스트(linked list)가 존재합니다.

 

연결리스트(linked list)의경우 동적메모리 할당을 이용하여 배열과는 다르게 선형 데이터 구조를 이루고 있으며

 

일종의 끈처럼 데이터 구조를 표현할 수 있다.

 

 

 

연결리스트는 배열이 가진 단점을 극복해내는 자료구조이다. 연결리스트는 크기를 동적으로 변경할수 있기 때문에

 

실행 도중 필요한 만큼 메모리를 확보할 수 있고, 필요없는 메모리는 삭제가 가능하다.

 

연결리스트의 단점으로는 포인터를 사용하기 때문에 사용법이 어렵고 오류가 났을때 문제점이 무엇인지 찾기 어렵다는점이다.

 

 


동적 메모리 할당


 

 

 

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

int	main(void){
	
	int *ptr = NULL;
	p2i = (int *)malloc(5*sizeof(int));
	
	//~~~~~
	
	free(p2i); 
}

 

malloc() 함수의 경우 stdlib.h헤더파일에 정의되어있으니 헤더파일을 포함하여야 한다.

malloc() 함수는 메모리를 할당받는 함수로 free 함수를 통해 메모리를 반납한다.

malloc() 함수는 반환되는 주소의 타입이 void* 이므로 주소를 받는 포인터에 맞춰 명시적인 타입 변환을 시켜주어야 한다.

 

예제4.1 ) 

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

typedef struct Movie_Strcut{
	char title[20]; //제목 
	int release; //개봉년도 
	int viewers; //관객수 
}movie;

int	main(void){
	
	int *iptr = (int *)malloc(sizeof(int));
	movie *mptr = (movie*)malloc(sizeof(movie));
	
	if((iptr == NULL )or(mptr == NULL)){
		printf("메모리 할당실패 \n");
		return (1);
	}
	*iptr = 20;
	printf("iptr 메모리할당후 : %d \n\n",*iptr);
	free(iptr);
	strcpy(mptr->title,"미나리");
	mptr->release = 2021;
	mptr->viewers = 100000;
	printf("mptr 메모리 할당후 제목 : %s		개봉연도: %d		관객수 %d",mptr->title,mptr->release,mptr->viewers);
	free(mptr);

	return 0;	
}

 


연결리스트(Linked list)


 

연결리스트는 하나의 구조체안에 필드로 다음 구조체를 가르키는 포인터와 데이터를 필드로 갖는 구조체를 의미한다.

 

예제) 단순 연결리스트 다루기 기초

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Node{
	int data;
	struct Node* link;
}Node;

int main(){
	Node *head, *temp;
	head = (Node *)malloc(sizeof(Node));
	
	if(head ==NULL)	exit(1);
	
	head->data = 10;
	head->link = NULL;
	
	temp = (Node *)malloc(sizeof(Node));
	if(temp ==NULL)	exit(1);
	
	temp->data = 20;
	temp->link = NULL;
	head->link = temp;
	
	printf("head-> %d ->%d \n",head->data, head->link->data);
	free(temp);
	free(head);
	
	return 0;
}

 

단순연결리스트 함수들

함수 설명 반환값  
create_node 동적으로 노드를 생성 노드 포인터  
count_nodes 연결리스트의 길이를 계산 길이  
search_node 연결리스트의 노드를 탐색 노드 포인터  
insert_node 연결리스트에 노드를 상비 없음  
delete_node 연결리스트에서 노드를 삭제 노드 포인터  
concatenate_lists 두 연결리스트의 결합 헤드 포인터  
reverse_list 연결리스트 순서를 반대로 변경 헤드포인터  

 

 

이어보기 

728x90
728x90

#include <stdio.h>
#include <stdlib.h> 
struct NODE{
	struct NODE* llink;
	char id[20];
	char dept[20];
	char name[20];
	char blood[20];
	float height;
	float weight;
	int year;
	struct NODE* rlink;
};

struct NODE* head;
struct NODE* tail;
char n_id[20],n_dept[20],n_name[20],n_blood[20];
float n_height,n_weight;
int n_year;
	
void init(){
	head = (struct NODE*)malloc(sizeof(struct NODE));
    tail = (struct NODE*)malloc(sizeof(struct NODE));
    
    head->rlink = tail;
    head->llink = head;
    tail->rlink = tail;
    tail->llink = head;
}

struct NODE* createnode(){
	struct NODE* node = (struct NODE*)malloc(sizeof(struct NODE));
	
	
	printf("id : ");
	scanf("%s",n_id);
	printf("dept : ");
	scanf("%s",n_dept);
	printf("name : ");
	scanf("%s",n_name);
	printf("blood : ");
	scanf("%s",n_blood);
	printf("height : ");
	scanf("%f",&n_height);
	printf("weight : ");
	scanf("%f",&n_weight);
	printf("year : ");
	scanf("%d",&n_year);
	
	node->year = n_year;
	node->height = n_height;
	node->weight = n_weight;
	
	for(int i = 0; i < 20; i++)
	{
		node->id[i] = n_id[i];
		node->dept[i] = n_dept[i];
		node->name[i] = n_dept[i];
		node->blood[i] = n_blood[i];
	}
	//내일배움카드 
	return (node);
}

void push_back(){
	struct NODE* newnode = createnode();
    struct NODE* p;
    p = tail;
    p->llink->rlink = newnode;
    newnode->llink = p->llink;
    p->llink = newnode;
    newnode->rlink = p;
}

void node_print(){
    struct NODE *p;
    p = head;
    //2.그래서 p를 한칸이동시켜주겠슴
	p = p->rlink; 
    while(p->rlink != tail){
    	//1헤드부터 출력됨9 
		printf("id : %s | dept : %s | name : %s | blood : %s | year : %d | height : %f | weight : %f \n",p->id,p->dept,p->name,p->blood,p->year,p->height,p->weight);	
        p = p->rlink;
    }
    printf("id : %s | dept : %s | name : %s | blood : %s | year : %d | height : %f | weight : %f \n",p->id,p->dept,p->name,p->blood,p->year,p->height,p->weight);	
        
}
void remove_node(){
	int num_year,del_count;
	struct NODE* p;
	
	printf("삭제할 학생의 생년월일(year) : ");
	scanf("%d",&num_year);
	
	
    p = head->rlink;
    while(p->rlink != tail){
        if(p->year == num_year){
            p->rlink->llink = p->llink;
            p->llink->rlink = p->rlink;
            free(p);
            return;
        }
        p = p->rlink;
    }
	
}
void search_node(){
	int num_year;
	
	struct NODE* p;
	p = head;
	
	printf("학생의 생년월일(year) : ");
	scanf("%d",&num_year);
	
	while(p->rlink != tail){
		if(p->year == num_year)
			printf("id : %s | dept : %s | name : %s | blood : %s | year : %d | height : %f | weight : %f \n",p->id,p->dept,p->name,p->blood,p->year,p->height,p->weight);	
        p = p->rlink;
	}
	
}

void free_node(){
	
}

int	main(){
	int menu = 0;
	init();
	while (menu != 5)
	{
		printf("학생 정보 관리 프로그램\n--------------------------------\n1. 학생 정보 입력\n2. 학생 정보 삭제\n3. 학생 검색\n4. 학생 정보 출력\n5. 프로그램 종료\n--------------------------------\n메뉴선택 : ");
		scanf("%d",&menu);
		switch(menu){
			
			case(1):
				push_back();
				break;
			case(2):
				remove_node();
				break;
			case(3):
				search_node();
				break;
			case(4):
				node_print();
				break;
			case(5):
				init();
				break;			
		}
	}
}

 

 

 

 

728x90
728x90

단일 연결리스트는 하나의 노드에 next가 다음노드의 주소를 가리키며 쭉 연결되어있는 리스트를

단일 연결리스트라고 하였습니다.

그렇다면 이중연결리스트는?

이중연결리스트는 말 그대로 모든 노드가 이전노드와 다음노드 에 대한 주소를 모두 저장학고있는 리스트를 의미합니다.


이중연결리스트는 단일연결리스트보다 약간의 메모리를 더 차지하긴 하겠지만 양방향 이동이 가능하기 때문에 리스트 삽입,삭제,추가 등을 할때 더욱 편리합니다. 

 

아래 사진을통해 간단하게 정리되어있길래 가져와봤습니다!  참고)movahws.tistory.com/113

 

 

 

 

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

struct NODE //구조체 선언
{
    struct NODE* llink;
    int data;
    struct NODE* rlink;
};
struct NODE* head;
struct NODE* tail;

//노드 생성 함수
struct NODE* makenode(int value){
    struct NODE *node = (struct NODE*)malloc(sizeof(struct NODE));
    node->llink = NULL;
    node->data = value;
    node->rlink = NULL;
    return node;
}

//출력 함수
void print(){
    struct NODE *p;
    p = head;
    while(p->rlink != tail){
        printf("%d-->",p->data);
        p = p->rlink;
    }
    printf("%d",p->data);
}

//초기화 함수
void init(){
    head = (struct NODE*)malloc(sizeof(struct NODE));
    tail = (struct NODE*)malloc(sizeof(struct NODE));
    head->data = 0;
    tail->data = 0;

    head->rlink = tail;
    head->llink = head;
    tail->rlink = tail;
    tail->llink = head;
}

//뒤로부터 노드 추가하는 함수
void push_back(int value){ 
    struct NODE* newnode = makenode(value);
    struct NODE* p;
    p = tail;
    p->llink->rlink = newnode;
    newnode->llink = p->llink;
    p->llink = newnode;
    newnode->rlink = p;
}

//main함수
int main(){
    init(); //head와 tail 초기화 (data = 0)
    push_back(10); //10 추가
    push_back(30); //30 추가
    push_back(50); //50 추가
    print();  //출력
    return 0;
}
728x90
728x90

해당 기능들을 본인의 취향대로 구현하시오 단 연결리스트를 이용하여 구현합니다. 

 

 

1. 헤더 파일, 구조체, 전역변수

 

헤더파일의 경우 기본적으로 입출력을위해 stdio 헤더파일과 메모리할당을 위해 stdlib.h 

그리고 문자열비교strcmp() 함수를 이용하기위해 string.h을 포함해주었다.

 

구조체는 위 문제와는 다르게 blood의 크기를 20으로 수정하였습니다. 

 

전역변수로는 struct node* head( =NODE *head ) 를 정의하였다. 

 

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

typedef struct node{
	struct node* next;
	int year;
	char id[20];
	char dept[20];
	char name[20];
	char blood[20];
	float height;
	float weight;
	
}NODE;

NODE *head = NULL;

 

main 함수

int main(void)
{
	// 리스트의 가장 처음 노드를 가르키는 포인터
	
	int menu = 0; 
	while(menu!=5){
		printf("학생 정리 관리 프로그램 \n --------------------------------------------------------------------------------\n1. 학생 정보 입력\n2. 학생 정보 삭제\n3. 학생 검색\n4. 학생 정보 출력\n5. 프로그램 종료\n--------------------------------------------------------------------------------\n메뉴 선택 : ");
		scanf("%d",&menu);
		
		switch(menu){
			case 1:
				addNode(&head); //학생정보 추가
				break;
			case 2:
				del_node(); //모든학생의 데이터 삭제 
				break;
			case 3:
				search_node(); //학생의 생년월일을 입력하고 해당학생을 찾아 출력
				break;
			case 4:
				print_node(); //모든학생정보를 출력
				break;
			case 5:
				free_node(); //종료
				break;
		}
	}
	return 0;
}

 

addNode()
//현재 리스트의 맨 뒤에 노드를 추가해주는 함수
void addNode(NODE **head)
{
	// 전달받은 값을 저장하는 새로운 노드를 생성한다.
	NODE *newNode = createNode();
	// 헤드에 아무것도 없을 경우
	// 즉, 현재 노드가 하나도 없을 경우
	if(*head == NULL)
	{
		// 헤드에 생성한 노드를 연결
		*head = newNode;
	}
	else
	{
		NODE *temp = *head;
		// 마지막 노드를 찾는 루프
		while(temp->next != NULL)
		{
			temp = temp->next;
		}
		// 마지막 노드일 경우 새로 생성한 노드 연결
		temp->next = newNode;
	}
}

del_node()

void del_node(){
	NODE * curr = head;
	char yesorno[20];
	
	printf("정말 모든학생의 정보를 삭제하시겠습니까? (yes or no) : ");
	scanf("%s",yesorno);
	
	if(strcmp(yesorno,"yes") ==0 || strcmp(yesorno,"YES") ==0 ) //yesorno가 yes이거나 YES일떄 strcmp비교를통해 같으면 0이 반환 됨 
	{
		head = NULL;
	}
}

 

search_node()

void search_node(){
	int check_year; 
	int n_count,check = 0;
	
	printf("찾을 학생의 생년월일 입력하세요ex)20000321 : ");
	scanf("%d",&check_year);
	
	NODE *cur = head;
	while(cur != NULL){ //head파일의 데이터부터 시작하여
		
		if(cur->year == check_year)	//생년월일이 일치할경우 출력
		{
		printf("id : %s | ",cur->id);
		printf("dept : %s | ",cur->dept);
		printf("year : %d | ",cur->year);
		printf("name : %s | ",cur->name);
		printf("height : %f | ",cur->height);
		printf("weight : %f | ",cur->weight);
		printf("blood : %s \n\n",cur->blood);
		}
			
		cur= cur->next; //출력후or스킵후 cur는 cur의next주소를 가리킴
	}
}

 

free_node()

void free_node(){
	NODE * curr = head;
	
	while(curr != NULL){
		free(curr);
		curr = curr->next;
	}
}

 

print_node()

void print_node(){
	NODE * curr = head;
	printf("\n+++++ 학생 정보 +++++\n");
	while(curr != NULL){			//curr는 head의 데이터부터 시작하여 한칸씩(여기서 한칸이란 NODE한칸)이동
		printf("id : %s | ",curr->id);
		printf("dept : %s | ",curr->dept);
		printf("year : %d | ",curr->year);
		printf("name : %s | ",curr->name);
		printf("height : %f | ",curr->height);
		printf("weight : %f | ",curr->weight);
		printf("blood : %s | ",curr->blood);
		printf("NODE(p) : %p\n",curr);
	
		curr = curr->next; //curr은 curr의 next(다음노드의 주소)를 저장한다
	}
	printf("+++++ 학생 정보 +++++\n\n");
}

 

전체코드

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

typedef struct node{
	struct node* next;
	int year;
	char id[20];
	char dept[20];
	char name[20];
	char blood[20];
	float height;
	float weight;
	
}NODE;

NODE *head = NULL;
int people_count = 0;
//전달받은 데이터를 저장하는 하나의 노드를 생성하는 함수
NODE* createNode()
{
	people_count++;
	int n_year;
	char n_id[20],n_dept[20],n_name[20],n_blood[20];
	float n_height,n_weight;
	NODE *temp = (NODE*)malloc(sizeof(NODE));
	
	printf("id : ");
	scanf("%s",n_id);
	printf("dept : ");
	scanf("%s",n_dept);
	printf("year : ");
	scanf("%d",&n_year);
	printf("name : ");
	scanf("%s",n_name);
	printf("height : ");
	scanf("%f",&n_height);
	printf("weight : ");
	scanf("%f",&n_weight);
	printf("blood : ");
	scanf("%s",n_blood);
	
	temp->year = n_year;
	temp->height= n_height;
	temp->weight = n_weight;
	
	for(int i =0; i<20; i++){
		temp->id[i] = n_id[i];
		temp->dept[i] = n_dept[i];
		temp->name[i] = n_name[i];
		temp->blood[i] = n_blood[i];  
	}
	
	temp->next = NULL;
	
	return temp;
}

//현재 리스트의 맨 뒤에 노드를 추가해주는 함수
void addNode(NODE **head)
{
	// 전달받은 값을 저장하는 새로운 노드를 생성한다.
	NODE *newNode = createNode();
	// 헤드에 아무것도 없을 경우
	// 즉, 현재 노드가 하나도 없을 경우
	if(*head == NULL)
	{
		// 헤드에 생성한 노드를 연결
		*head = newNode;
	}
	else
	{
		NODE *temp = *head;
		// 마지막 노드를 찾는 루프
		while(temp->next != NULL)
		{
			temp = temp->next;
		}
		// 마지막 노드일 경우 새로 생성한 노드 연결
		temp->next = newNode;
	}
}

void print_node(){
	NODE * curr = head;
	printf("\n+++++ 학생 정보 +++++\n");
	while(curr != NULL){
		printf("id : %s | ",curr->id);
		printf("dept : %s | ",curr->dept);
		printf("year : %d | ",curr->year);
		printf("name : %s | ",curr->name);
		printf("height : %f | ",curr->height);
		printf("weight : %f | ",curr->weight);
		printf("blood : %s | ",curr->blood);
		printf("NODE(p) : %p\n",curr);
	
		curr = curr->next;
	}
	printf("+++++ 학생 정보 +++++\n\n");
}

void free_node(){
	NODE * curr = head;
	
	while(curr != NULL){
		free(curr);
		curr = curr->next;
	}
}

void del_node(){
	NODE * curr = head;
	char yesorno[20];
	
	printf("정말 모든학생의 정보를 삭제하시겠습니까? (yes or no) : ");
	scanf("%s",yesorno);
	
	if(strcmp(yesorno,"yes") ==0 || strcmp(yesorno,"YES") ==0 ) //yesorno가 yes이거나 YES일떄 strcmp비교를통해 같으면 0이 반환 됨 
	{
		head = NULL;
	}
}

void search_node(){
	int check_year; 
	int n_count,check = 0;
	
	printf("찾을 학생의 생년월일 입력하세요ex)20000321 : ");
	scanf("%d",&check_year);
	
	NODE *cur = head;
	while(cur != NULL){
		
		if(cur->year == check_year)
		{
		printf("id : %s | ",cur->id);
		printf("dept : %s | ",cur->dept);
		printf("year : %d | ",cur->year);
		printf("name : %s | ",cur->name);
		printf("height : %f | ",cur->height);
		printf("weight : %f | ",cur->weight);
		printf("blood : %s \n\n",cur->blood);
		}
			
		cur= cur->next;
	}
}

int main(void)
{
	// 리스트의 가장 처음 노드를 가르키는 포인터
	
	int menu = 0; 
	while(menu!=5){
		printf("학생 정리 관리 프로그램 \n --------------------------------------------------------------------------------\n1. 학생 정보 입력\n2. 학생 정보 삭제\n3. 학생 검색\n4. 학생 정보 출력\n5. 프로그램 종료\n--------------------------------------------------------------------------------\n메뉴 선택 : ");
		scanf("%d",&menu);
		
		switch(menu){
			case 1:
				addNode(&head);
				break;
			case 2:
				del_node(); //학생의 이름을 입력하고 이름이 일치하는 학생을 모두삭제 
				break;
			case 3:
				search_node();
				break;
			case 4:
				print_node();
				break;
			case 5:
				free_node();
				break;
		}
	}
	retu

 

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

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

//전달받은 데이터를 저장하는 하나의 노드를 생성하는 함수
NODE* createNode(int data)
{
	NODE *temp = (NODE*)malloc(sizeof(NODE));
	temp->next = NULL;
	temp->data = data;
	return temp;
}

//현재 리스트의 맨 뒤에 노드를 추가해주는 함수
void addNode(NODE **head, int data)
{
	// 전달받은 값을 저장하는 새로운 노드를 생성한다.
	NODE *newNode = createNode(data);
	// 헤드에 아무것도 없을 경우
	// 즉, 현재 노드가 하나도 없을 경우
	if(*head == NULL)
	{
		// 헤드에 생성한 노드를 연결
		*head = newNode;
	}
	else
	{
		NODE *temp = *head;
		// 마지막 노드를 찾는 루프
		while(temp->next != NULL)
		{
			temp = temp->next;
		}
		// 마지막 노드일 경우 새로 생성한 노드 연결
		temp->next = newNode;
	}
}

int main(void)
{
	// 리스트의 가장 처음 노드를 가르키는 포인터
	NODE *head = NULL;
	// 맨 뒤에 데이터 '10'을 가진 노드를 추가
	addNode(&head, 10);
	// 맨 뒤에 데이터 '20'을 가진 노드를 추가
	addNode(&head, 20);
	// 맨 뒤에 데이터 '30'을 가진 노드를 추가
	addNode(&head, 30);
	
	NODE * curr = head;
	while(curr != NULL){
		printf("%d\n",curr->data);
		curr = curr->next;
	}
	curr = head -> next;
	
	while(curr != NULL){
		free(curr);
		curr = curr->next;
	}
	
	return 0;
}

 

 

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <stdio.h>
#include <stdlib.h>
 
typedef struct node{
    int data;
    struct node* next;
}NODE;
 
//전달받은 데이터를 저장하는 하나의 노드를 생성하는 함수
NODE* createNode(int data)
{
    NODE *temp = (NODE*)malloc(sizeof(NODE));
    temp->next = NULL;
    temp->data = data;
    return temp;
}
 
//현재 리스트의 맨 뒤에 노드를 추가해주는 함수
void addNode(NODE **head, int data)
{
    // 전달받은 값을 저장하는 새로운 노드를 생성한다.
    NODE *newNode = createNode(data);
    // 헤드에 아무것도 없을 경우
    // 즉, 현재 노드가 하나도 없을 경우
    if(*head == NULL)
    {
        // 헤드에 생성한 노드를 연결
        *head = newNode;
    }
    else
    {
        NODE *temp = *head;
        // 마지막 노드를 찾는 루프
        while(temp->next != NULL)
        {
            temp = temp->next;
        }
        // 마지막 노드일 경우 새로 생성한 노드 연결
        temp->next = newNode;
    }
}
 
int main(void)
{
    // 리스트의 가장 처음 노드를 가르키는 포인터
    NODE *head = NULL;
    // 맨 뒤에 데이터 '10'을 가진 노드를 추가
    addNode(&head, 10);
    // 맨 뒤에 데이터 '20'을 가진 노드를 추가
    addNode(&head, 20);
    // 맨 뒤에 데이터 '30'을 가진 노드를 추가
    addNode(&head, 30);
    
    NODE * curr = head;
    while(curr != NULL){
        printf("%d\n",curr->data);
        curr = curr->next;
    }
    curr = head -> next;
    
    while(curr != NULL){
        free(curr);
        curr = curr->next;
    }
    
    return 0;
}
cs

 

 

728x90
728x90

 

코딩도장

#include <stdio.h>
#include <stdlib.h>
/*
2020-11-27 node add
*/
struct NODE{
	struct NODE *next;
	int data;
};

void insert_node(struct NODE *target, int data){	//기준노드뒤에  노드를 추가하는 함수 
	struct NODE *newNode = (struct NODE*)malloc(sizeof(struct NODE)); //새 노드생성 
	newNode->next = target->next; //새 노드의 다음노드에 기준노드의 다음노드ㅇ를 지정 
	newNode -> data = data; 
	target->next = newNode; //기준노드의 다음노드에 새 노드를 지정 
}

int		main(){
	struct NODE *head = (struct NODE*)malloc(sizeof(struct NODE));
	 
	head->next = NULL;
	
	insert_node(head,11);
	insert_node(head,22);
	insert_node(head,33); 
	
	struct NODE *curr = head->next;
	
	while(curr != NULL){
		printf("%d\n",curr->data);
		curr= curr->next;
	}
	
	curr = head->next;      // 연결 리스트 순회용 포인터에 첫 번째 노드의 주소 저장
    while (curr != NULL)    // 포인터가 NULL이 아닐 때 계속 반복
    {
        struct NODE *next = curr->next;    // 현재 노드의 다음 노드 주소를 임시로 저장
        free(curr);                        // 현재 노드 메모리 해제
        curr = next;                       // 포인터에 다음 노드의 주소 저장
    }
    
    free(head);
    
    return (0);
}

 

리스트 구조를 구현하는데에 가장 기본적인 방법인 자료구조입니다.

 

리스트를 구성하고 있는 가장 기본적인 단위인 노드(Node) 의 구조입니다. 

 

 데이터

다음노드 포인터

                                         <노드의 구조>

 

각각의 노드를 연결해주면 연결리스트(링크드리스트) 가 됩니다.

 

 

<다른 예제코드>

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

노드의 구조체

typedef struct ListNode

{

int data; //데이터값

struct ListNode* NextNode; // 다음노드의 주소

} Node;

 

새로운 노드생성

Node* CreateNode(int newData)

{

Node* NewNode = (Node*)malloc(sizeof(Node)); //새로운 노드를 생성합니다.

NewNode->data = newData; //데이터저장

NewNode->NextNode = null; // 다음노드에 null로 초기화

 

return NewNode; //노드의 주소를 반환합니다.

}

 

연결리스트에 노드추가(새로만든노드를 연결리스트 맨마지막에 붙이는함수)

void AppendNode(Node** Head, Node* NewNode)

{

if((*Head) ==NULL)

{

*Head = NewNode;  //헤드노드가 null = 리스트가 없다 --> 새로만든 노드를 헤드노드로 지정한다.

}

else

{

Node* Tail = (*Head);  //헤드가 현재 테일이다.

while(Tail->NextNode != null) // 현재의 다음노드가 있으면

{

Tail = Tail->NextNode;  //현재의 다음노드가 테일이 된다.

}

 

Tail->NextNode = NewNode; // 다음노드에 새로만든 노드를 추가한다.

}

}

 

노드 삽입

 

void InsertNode(Node* current , Node* NewNode)

{

NewNode->NextNode = current ->NextNode;

current->NextNode = NewNode;

}

 

 

 

728x90
728x90

자료구조에는 크게 선형구조와 비선형구조로 나누어지고

 

그중에서 선형구조에서의 스택(Stack)에 대해 알아보겠습니다.

 

<지난 글>

ititit1.tistory.com/75

 

[ 자료구조 ] 자료구조의 기초 선형 구조와 수식 계산

1.자료구조란? 자료구조(資料構造, 영어: data structure)는 전산학에서 자료를 효율적으로 이용할 수 있도록 컴퓨터에 저장하는 방법이다. 신중히 선택한 자료구조는 보다 효율적인 알고리즘을 사

ititit1.tistory.com

 

 

스택(Stack)란? 

 

자료구조의 매우 기초적인 개념인 Stack이란 영어로 쌓아놓은 더미란 뜻입니다.

 

LIFO(Last In First Out) 방식으로 가장 최근에 들어온 데이터가 가장 먼저 나가게 됩니다.

 

 

스택은 push를통해 값을 넣어주고 pop을 통해 데이터를 꺼내옵니다.

 

push를 할경우 top은 처음에 -1로 초기화하며 전위연산을 통해  Stack[++top] 즉 인덱스를 1더한다음 그 인덱스에 값을 넣어줍니다 

 

pop은 값을 반환하는 함수인데  Stack[pop--] 값을 꺼내온다음 pop-- 후위연산을 통해 인덱스를 1뺴줍니다.

 

이렇게할경우 stack 의 가장 위에있는값 Stack[pop] 즉 pop는 유동적으로 변합니다.

 

 

<소스코드>

 

#include <stdio.h>
#define MAX_STACK_SIZE 100
/*
2020-11-26 JinSol Stack
가장 최근에 들어온 데이터가 가장먼저 나감 
*/

int stack[MAX_STACK_SIZE];
int top = -1;
int bottom = 0;

//스택이 비어있는지 확인
int IsEmpty(){
	if(top<0)
		return (true);
	else
		return (false);
}
//스택이 가득차있는지 확인
int IsFull(){
	if(top >= MAX_STACK_SIZE-1)
		return (true);
	else
		return (false);
}

//스택에 값을 넣어줌
void push(int value){
	if(IsFull() == true)
		printf("스택이 가득차있음\n");
	else
		stack[++top] = value;
}
//스택에서 값을 빼옴 
int	pop(){
	if(IsEmpty() == true )
		printf("스택이 비어있음\n");
	else
		return (stack[top--]);
}
int	main(void){
	
	push(5);
	push(12);
	push(-5);
	push(0);
	push(1);
	
	printf("%d \n",pop());
	printf("%d \n",pop());
	printf("%d \n",pop());
	printf("%d \n",pop());
	printf("%d \n",pop());
	return (0);
}

 

<실행결과>

 

 

 

728x90
728x90

 

1.자료구조란?

자료구조(資料構造, 영어: data structure)는 전산학에서 자료를 효율적으로 이용할 수 있도록 컴퓨터에 저장하는 방법이다. 신중히 선택한 자료구조는 보다 효율적인 알고리즘을 사용할 수 있게 한다.



2. 자료구조 분류 

 

 

자료구조는 크게 선형구조와 비선형구조로 나누어진다. 선형구조란?

국어사전

선형적 

(線形的)

[선형적]

  • 선처럼 길게 일렬로 나아가는. 또는 그런 것.

 

말그대로 데이터들이 선처럼 길에 일렬로 나아가는 구조를 선형구조라고 한다. 선형구조에는 배열 연결리스트 스택 큐

등이 포함됩니다. 스택은 일반적으로  수식계산에서 많이사용되며 스택과 큐(스택+큐)가 사용되는 구조를 데큐(Deque)라고 한다.

 

 

선형구조

비선형구조란 하나의 자료 뒤에 여러개의 자료가 존재할 수 있는 것을 의미 합니다.

비선형구조

 

 

3. 전위표기법과 후위 표기법

 

 

우리가 일상생활에서 쓰이는 표기법의 경우 중위표기(Infix)를 사용하고있다

 

그렇다면 전위표기(Prefix)와 후위표기(Postfix)란?

 

전위표기란 연산자를 피연산자 앞에 표기하는방법이다

 

후위표기란 연산자를 피연산자 뒤에 표기하는 방법

 

 

중위 표기법(infix notation) : 연산자를 연산 대상의 가운데에 쓰는 표기법(Ex : 5 + 2 / 7) ㄴ> 일상생활에서 쓰이는 표기법 
전위 표기법(prefix notation) : 연산자를 연산 대상의 앞에 쓰는 표기법(Ex : + 5 / 2 7)
후위 표기법(postfix notation) : 연산자를 연산 대상의 뒤에 쓰는 표기법(Ex : 5 2 7 / +)

 

 

1 2 * 3 1 - / 4 5 * +

해당 후위 표기 방식을 중위 표기 방식으로 바꾸면 아래와 같습니다.

(1 * 2) / (3 - 1) + (4 * 5)

따라서 해당 값을 계산하면 21입니다.

 

+ - 5 4 / * 2 3 * 2 1

해당 전위 표기 방식을 중위 표기 방식으로 바꾸면 아래와 같습니다.

(5-4) + ((2*3) / (2*1))

따라서 해당 값을 계산하면 4입니다.

 

 

728x90
728x90

연결리스트 (linked list) 란?

 

각 노드가 데이터와 포인터를 가지고 한줄로 연결되어 있는 방식으로 데이터를 저장하는 자료구조입니다.

데이터를 담고있는 노드들이 연결되어있는데 노드의 포인터가 다음or이전의 노드와 연결되어있다.

 

 

 

Linked list

 

struct NODE {   // 연결 리스트의 노드 구조체
    struct NODE *next;    // 다음 노드의 주소를 저장할 포인터
    int data;             // 데이터를 저장할 멤버
};

 

Node구조체에서 struct NODE *next; 이부분은 다음노드(or이전노드)의 메모리 주소(포인터) 를 저장해야한다.

즉 자기 자신이 아닌 다른 노드의 메모리 주소를 저장하고있다. 이점이 매우 중요하고 핵심이다.

위 예제에서는 int 형 data를 하나만 넣었지만 String int char등 여러개의 데이터가 구조체 멤버에 들어갈수있다.

 

 

단일 연결리스트의 노드 종류

 

º head node :  단일 연결리스트의 기준점이며 헤드 노드(head node)라고 부른다. 헤드 노드는 첫번째 노드를 가리키며

데이터를 저장하지 않는다.

º 노드(node)  : 단일 연결리스트에서 데이터가 저장되는 실제 노드이다.

 

#include <stdio.h>
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

typedef struct node {             // 연결 리스트의 노드 구조체
    struct node *next;    // 다음 노드의 주소를 저장할 포인터
    int data;             // 데이터를 저장할 멤버
}NODE;


int main()
{
    NODE *head = (NODE*)malloc(sizeof( NODE));    // 머리 노드 생성
                                                  // 머리 노드는 데이터를 저장하지 않음

    NODE *node1 = (NODE*)malloc(sizeof( NODE));   // 첫 번째 노드 생성
    head->next = node1;                                 // 머리 노드 다음은 첫 번째 노드
    node1->data = 10;                                   // 첫 번째 노드에 10 저장

     NODE *node2 = (NODE*)malloc(sizeof( NODE));   // 두 번째 노드 생성
    
    node1->next = node2;                                // 첫 번째 노드 다음은 두 번째 노드
    node2->data = 20;                                   // 두 번째 노드에 20 저장

    node2->next = NULL;                                 // 두 번째 노드 다음은 노드가 없음(NULL)

    NODE *curr = head->next;    // 연결 리스트 순회용 포인터에 첫 번째 노드의 주소 저장
    while (curr != NULL)               // 포인터가 NULL이 아닐 때 계속 반복
    {
        printf("%d\n", curr->data);    // 현재 노드의 데이터 출력
        curr = curr->next;             // 포인터에 다음 노드의 주소 저장
    }

    free(node2);    // 노드 메모리 해제
    free(node1);    // 노드 메모리 해제
    free(head);     // 머리 노드 메모리 해제

    return 0;
}

 

<실행결과>

 

 

<예제2>

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

//start = head
struct node{
	struct node* next;
	int age;
	
};

int	main(){
	
	struct node* start = (struct node*) malloc(sizeof(struct node));
	
	struct node* node1 = (struct node*) malloc(sizeof(struct node));
	start -> next = node1;
	
	node1 -> age = 100;
	
	struct node* node2 = (struct node*) malloc(sizeof(struct node));
	node1 -> next = node2;
	node2 -> age = 200;
	
	struct node* node3 = (struct node*)malloc(sizeof(struct node));
	node2 -> next = node3;
	node3 -> age = 400;
	
	node3 -> next = NULL;
	
	struct node* ptr = start->next;
	
	
	
	while(ptr != NULL){
		printf("%d\n",ptr->age);
		ptr=ptr->next;
	}
	
	return 0;
	
}

 

728x90

+ Recent posts