Last In First Out의 구조를 가진 " Stack "에 대해서 배워보자!

ex) 식당 아주머니는 식판을 아래에서부터 쌓아올리지만, 식판을 가져가는 우리는 위에서부터 가져간다!

     지역 변수의 사용

- 수직적인 구조이다.

- push : 스택이라는 메모리에 데이터를 저장하는 인터페이스

- pop :  스택이라는 메모리부터 데이터를 꺼내오는 인터페이스











프로젝트명 : 20140212

파일명 : 1.c


// 스택(Stack) : LIFO(Last In First Out)
// ex)식당에서의 식판, 지역 변수의 사용

// push : 스택이라는 메모리에 데이터를 저장하는 인터페이스
// pop : 스택이라는 메모리부터 데이터를 꺼내오는 인터페이스

#include <stdio.h>

#define MAX_SIZE	(5)

int arr[MAX_SIZE];
int idx;	//초기화해주지 않아도, os가 자체적으로 0으로 초기화

//push의 경우 뭘로 return할지 굳이 표시하지 않아도 된다.
void push(int data) {
	arr[idx++] = data;
	/* arr[idx] = data;	//최초의 push의 경우 0부터 시작한다고 했으니
	++idx; */
}

int pop() {
	return arr[--idx];
	/*
	--idx;
	return arr[idx]; */
}

//참(0 이외의 수)과 거짓(0)을 나타내려면 int 타입을 쓴다.
int is_full() {
	return (idx == MAX_SIZE);
	/*
	if(idx == MAX_SIZE)
		return 1;
	else
		return 0;
	*/
}

int is_empty() {
	return (idx ==0);
	/*
	if(idx ==0)
		return 1;
	else
		return 0;
	*/
}

void main() {
	int i;

	for(i=0; i<10; i++) {
		if(!is_full())	//가득 차 있지 않아야 push가능
			push(i+1);	//1 2 3 4 5 6 7 8 9 10
	}

	for(i=0; i<10; i++) {
		if(!is_empty())
			printf("%d\n", pop());
	}
}



step 1. 가장 간단한 스택의 구현

#include <stdio.h>

#define MAX_SIZE	(5)

int arr[MAX_SIZE];
int idx;	//초기화해주지 않아도, os가 자체적으로 0으로 초기화

void push(int data) {arr[idx++] = data;}
int pop() {	return arr[--idx]; }
int is_full() { return (idx == MAX_SIZE); }
int is_empty() { return (idx ==0); }

void main() {
	int i;

	for(i=0; i<10; i++) {
		if(!is_full())	//가득 차 있지 않아야 push가능
			push(i+1);	//1 2 3 4 5 6 7 8 9 10
	}

	for(i=0; i<10; i++) {
		if(!is_empty())
			printf("%d\n", pop());
	}
}

step2. 하나 이상의 자료구조 구현

//step 2. 하나 이상의 자료구조 구현!
#include <stdio.h>

#define MAX_SIZE	(5)

// 데이터 추상화를 ADT(Abstract Data Type)
typedef struct __STACK {
	int arr[MAX_SIZE];
	int idx;
} STACK;

int arr[MAX_SIZE];
int idx;	//초기화해주지 않아도, os가 자체적으로 0으로 초기화

void push(int data, STACK *s) { s->arr[(s->idx)++] = data; }
int pop(STACK *s) {	return s->arr[--(s->idx)];}
int is_full(STACK *s) {	return (s->idx == MAX_SIZE);}
int is_empty(STACK *s) { return (s->idx ==0);}

void main() {
	int i;
	STACK s = {0, };	//이 데이터를 어떻게 처리할지는 라이브러리 개발하고 분석한 사람만 사용할 수 있다.
	//라이브러리 개발자가 저 스택을 초기화해줘야한다. -> step3

	for(i=0; i<10; i++) {
		if(!is_full(&s))	//가득 차 있지 않아야 push가능
			push(i+1, &s);	//1 2 3 4 5 6 7 8 9 10
	}

	for(i=0; i<10; i++) {
		if(!is_empty(&s))
			printf("%d\n", pop(&s));
	}
}

step3. 자료구조의 초기화를 위한 인터페이스 지급

// step 3 : 자료구조의 초기화를 위한 인터페이스 지급
// 스택의 크기가 고정되어있고,  사용자가 우너하는 시점에 메모리를 할당해야하기때문ㅇ ㅔ자료구조로...->step4
#include <stdio.h>

#define MAX_SIZE	(5)

// 데이터 추상화를 ADT(Abstract Data Type)
typedef struct __STACK {
	int arr[MAX_SIZE];
	int idx;	// =0;	//?
} STACK;

void init_stack(STACK *s) { s->idx = 0; }
void push(int data, STACK *s) { s->arr[(s->idx)++] = data; }
int pop(STACK *s) {	return s->arr[--(s->idx)];}
int is_full(STACK *s) {	return (s->idx == MAX_SIZE);}
int is_empty(STACK *s) { return (s->idx ==0);}

void main() {
	int i;
	STACK s;
	init_stack(&s);

	for(i=0; i<10; i++) {
		if(!is_full(&s))	//가득 차 있지 않아야 push가능
			push(i+1, &s);	//1 2 3 4 5 6 7 8 9 10
	}

	for(i=0; i<10; i++) {
		if(!is_empty(&s))
			printf("%d\n", pop(&s));
	}
}

step4. 자료 구조를 힙에 구현

// step 4.  자료구조를 힙에 구현
#include <stdio.h>
#include <stdlib.h>

typedef struct __STACK {
	#define MAX_SIZE	(5)
	int *arr;	//힙에 구현
	int idx;
} STACK;

void init_stack(STACK *s) { 
	s->arr = (int*)malloc(sizeof(int)*MAX_SIZE);
	s->idx = 0;
}
void push(int data, STACK *s) { s->arr[(s->idx)++] = data; }
int pop(STACK *s) {	return s->arr[--(s->idx)];}
int is_full(STACK *s) {	return (s->idx == MAX_SIZE);}
int is_empty(STACK *s) { return (s->idx ==0);}

void main() {
	int i;
	STACK s;
	init_stack(&s);

	for(i=0; i<10; i++) {
		if(!is_full(&s))	//가득 차 있지 않아야 push가능
			push(i+1, &s);	//1 2 3 4 5 6 7 8 9 10
	}

	for(i=0; i<10; i++) {
		if(!is_empty(&s))
			printf("%d\n", pop(&s));
	}
}

step5. 범용 타입에 대한 설계------------------------------

// step 5. 범용 타입에 대한 설계
#include <stdio.h>
#include <stdlib.h>

typedef struct __STACK {
	#define MAX_SIZE	(5)
	int *arr;	//모든 타입이 다 되게 해야 될 때는 void 포인터 타입으로
	int idx;
} STACK;

void init_stack(STACK *s) { 
	s->arr = (int*)malloc(sizeof(int)*MAX_SIZE);
	s->idx = 0;
}
void push(int data, STACK *s) { s->arr[(s->idx)++] = data; }
int pop(STACK *s) {	return s->arr[--(s->idx)];}
int is_full(STACK *s) {	return (s->idx == MAX_SIZE);}
int is_empty(STACK *s) { return (s->idx ==0);}

void main() {
	int i;
	STACK s;
	init_stack(&s);

	for(i=0; i<10; i++) {
		if(!is_full(&s))	//가득 차 있지 않아야 push가능
			push(i+1, &s);	//1 2 3 4 5 6 7 8 9 10
	}

	for(i=0; i<10; i++) {
		if(!is_empty(&s))
			printf("%d\n", pop(&s));
	}
}

------------------------------------


// 스택의 내부 자료구조를 리스트로 구현!
#include <stdlib.h>
#include <stdio.h>

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

typedef struct __STACK
{
	int idx;	// 스택에 저장된 위치
	int size;	// 스택의 크기
	struct __NODE *head;
} STACK;

void init_stack(STACK *s, int size)
{
	s->idx = 0;
	s->size = size;
	s->head = 0;
}

void push(int data, STACK *s) {
	NODE *cur;
	NODE *node = (NODE*)malloc(sizeof(NODE));
	node->data = data;
	node->next = 0;

	// 리스트가 비어 있는 경우
	if(s->head ==0) {
		s->head = node;
		++(s->idx);
		return;
	}

	// 리스트가 비어 있지 않은 경우
	cur = s->head;
	while(cur->next)
		cur = cur->next;

	cur->next = node;
        ++(s->idx);

}



int pop(STACK *s)
{
	int data;
	NODE *prev = s->head;
	NODE *cur = s->head;

	while(cur->next)
	{
		prev = cur;
		cur = cur->next;
	}

	data = cur->data;
	prev->next = 0;
	--(s->idx);
	free(cur);

	return data;
}

int is_full(STACK *s) { return s->size == s->idx; }
int is_empty(STACK *s) { return s> idx == 0; }

void main()
{
	int i;

	STACK s;
	init_stack(&s, 3);

	for(i = 0; i < 4; i++)
	{
		if(!is_full(&s)) push(i+1, &s);
	}

	for(i = 0; i < 4; i++)
	{
		if(!is_empty(&s)) printf("%d\n", pop(&s));
	}
}

------------------

파일명 : 2.c


//비트셋(Bitset, Bitmap
// LED 제어 프로그램 - 메모리의 낭비가 일어나고있다.
#include <stdio.h>
#include <stdlib.h>


enum { LED0 = 0, LED1, LED2, LED3, LED4, LED5, LED6, LED7 };
enum { LED_OFF = 0, LED_ON = 1 };
void main()
{
	int i;
	char mmio[8] = {0, };

	// LED ON
	mmio[LED1] = LED_ON;
	mmio[LED3] = LED_ON;

	// LED CHECK
	for(i=0;i<8;i++){
		if(mmio[i] == LED_ON)
			printf("LED%d ON\n", i);
		else
			printf("LED%d OFF\n", i);
	}
	getchar(); system("cls");

	// LED OFF
	mmio[LED3] = LED_OFF;

	// LED CHECK
	for(i=0;i<8;i++){
		if(mmio[i] == LED_ON)
			printf("LED%d ON\n", i);
		else
			printf("LED%d OFF\n", i);
	}
}

위의 소스코드는 메모리의 낭비라는 문제점이 있다. 다음 소스코드는 그를 수정하였다.

// 문제점: 메모리의 낭비
#include <stdio.h>
#include <stdlib.h>

enum { LED0 = 0, LED1, LED2, LED3, LED4, LED5, LED6, LED7 };
enum { LED_OFF = 0, LED_ON = 1 };

// 비트 연산으로 변경해보세요!

// 시프트 연산자

// 데이터 << 이동할 비트 수
// 데이터 >>  이동할 비트 수

// LED 제어 프로그램 - 메모리의 낭비가 일어나고있다.

void main()
{
	int i;
	char mmio = 0;	// // char mmio[8] = { 0, };

	// LED ON
	mmio = mmio | (LED_ON << LED1);	// 0000 0000 mmio = 0
									// 0000 0010 LED_ON	<< LED1
									// --------- |(OR)
									// 0000 0010
	
	mmio |= LED_ON >> LED3;			// 복합 대입 연산자의 사용
	// 규칙 1. 특정 비트를 설정하려면 OR 연산자를 사용해야 한다!


	// 0000 1010
	// 0000 0010	// 마스크 비트
	// --------- &
	// 0000 0010

	// LED CHECK
	for(i=0; i<8; i++)
	{
		if(mmio & (LED_ON << i))	// 0000 1010 & 1 << i
			printf("LED%d ON\n", i);
		else
			printf("LED%d OFF\n", i);
	}
	// 규칙 2. 특정 비트를 검사하려면 &연산자를 사용해야 한다.

	getchar(); system("cls");

	// LED OFF
	//mmio[LED3] = LED_OFF;	// 0000 1010
							// 1111 0111	~(LED_ON << LED3)
							// --------- &
							// 0000 0010
	mmio &= ~(LED_ON << LED3); //비트를 끈거다.

	// 규칙 3. 특정 비트를 초기화하려면 &연산자와 비트 반전 연산자(~)
	// 를 사용해야 한다.

	// LED CHECK
	for(i=0; i<8; i++)
	{
		if(mmio & (LED_ON << i))
			printf("LED%d ON\n", i);
		else
			printf("LED%d OFF\n", i);
	}
}

c

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

#define BIT_SET(i , x)  ((x[i/32]) |= (1>>(i%32)))
#define BIT_ISSET(i , x) ((x[i/32]) & (i >>(>i%32)))
#define BIT_CLR(i , x)  ((x[[i/32]) &= ~(i <>>(i%32)))

enum { LED0 = 0, LED1, LED2, LED3, LED4, LED5, LED6, LED7 };
enum { LED_OFF = 0, LED_ON = 1 };

// 비트 연산으로 변경해보세요!

// 시프트 연산자

// 데이터 << 이동할 비트 수
// 데이터 >> 이동할 비트 수

void main()
{
	int i;
	//char mmio = 0;	// 32비트 -> 128비트
	int mmio[32] = {0,};
	// LED ON

	BIT_SET(LED1, mmio);
	BIT_SET(1000, mmio);
	//mmio = mmio | (LED_ON <<LED1);	// 0000 0000 mmio = 0
	// 0000 0010 LED_ON	<< LED1
	// --------- |(OR)
	// 0000 0010

	// 복합 대입 연산자의 사용



	for (i = 0; i<1024; i++)
	{
		if (BIT_ISSET(i, mmio))	// 0000 1010 & 1 << i
			printf("LED%d ON\n", i);
		else
			printf("LED%d OFF\n", i);
	}

	getchar(); system("cls");


	mmio &= ~(LED_ON << LED3);


	// LED CHECK
	for (i = 0; i<128; i++)
	{
		if (BIT_CLR(i, mmio))
			printf("LED%d ON\n", i);
		else
			printf("LED%d OFF\n", i);
	}
}

e

f

파일명 : 3.c

//Dynamic Array
#include <stdio.h>

#define ARR_SIZE(x)	(sizeof(arr)/sizeof(*arr))

int sum_arr(int arr[]) {
	int i, sum = 0;
	for(i=0;i<ARR_SIZE(arr);i++) {
		sum += arr[i];
	}
	return sum;
}

void main() {
	int i, sum = 0;
	int arr[] = {1,2,3,4,5,6,7,8,9,10};

	//for(i=0;i<ARR_SIZE(arr);i++)
	//	sum += arr[i];

	printf("sum=%d\n", sum_arr(arr));
}

a

//이 소스코드의 단점 : 배열에 있는 컨텐츠를 저장하는데, 저장되는 타입이 int이다. 
//근데 앞으로 double, float, char타입의 배열이 만들수도있는거다. 
//즉 모든 것이 성립하는 void 타입으로 바꿔야 할것이다.
//즉 int타입만 저장 가능하다
#include <stdio.h>
#include <stdlib.h>	//calloc 사용하기 위해서 선언한다.

typedef struct __Array {
	int capacity;
	int *content;
} Array;

Array* createArray(int capacity) {
	Array *arr = (Array*)calloc(1, sizeof(struct __Array));
	arr->content = (int*)calloc(capacity, sizeof(int));
	arr->capacity = capacity;

	return arr;
}

int setElement(Array *arr, int index, int data) {
	int capacity = arr->capacity;
	if(index <0 || index >=capacity)
		return -1;

	arr->content[index] = data;
	return 0;
}

int getElement(Array *arr, int index) {
	int capacity = arr->capacity;
	if(index <0 || index >capacity) {
		fprintf(stderr, "out of index");
		exit(-1);
	}

	return arr->content[index];
}

int getCapacity(Array *arr) { return arr->capacity; }

int sum_arr(Array *arr) {
	int i, sum = 0;
	for(i=0;i<getCapacity(arr);i++)
		sum +=getElement(arr, i);
	return sum;
}

void main() {
	int i;
	Array *arr = createArray(5);	//int arr[5];만든것과 동일

	for(i=0;i<getCapacity(arr);i++) {
		setElement(arr, i, i+1); //arr[i] = i+1;
	}

	printf("sum = %d\n", sum_arr(arr));

	/*for(i=0;i<getCapacity(arr);i++)
		printf("arr[%d] = %d\n", i, getElement(arr, i));
		printf("arr[%d] = %d\n", i, arr[i]);	//이건 안된다. 왜냐하면 arr은 배열이아니라 구조체니까 */
 }


// 문제점: 특정 타입만을 저장할 수 있음!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct __Array
{
	int capacity;
	void **content;
} Array;

Array* createArray(int capacity)
{
	Array *arr = (Array*)calloc(1, sizeof(struct __Array));
	arr->content = (void**)calloc(capacity, sizeof(void*));
	arr->capacity = capacity;

	return arr;
}

void* setElement(Array *arr, int index, void *pointer)
{
	void *old;
	int capacity = arr->capacity;
	if(index < 0 || index>= capacity)
	{
		fprintf(stderr, "out of index");
		exit(-1);
	}


	old = arr->content[index];	// backup
	arr->content[index] = pointer;
	return old;
}

void* getElement(Array *arr, int index)
{
	int capacity = arr->capacity;
	if(index < 0 || index > capacity)
	{
		fprintf(stderr, "out of index");
		exit(-1);
	}

	return arr->content[index];
}

int getCapacity(Array *arr) { return arr->capacity; }

typedef struct
{
	char name[32];
	int  age;
} PERSON;


void main()
{
	int i;
	PERSON *p;
	Array *arr = createArray(5);	// int arr[5];
									// int[] arr = new int[5];
	for(i = 0; i < getCapacity(arr); i++)
	{
		p = (PERSON*)malloc(sizeof(PERSON));
		strcpy(p->name, "kkk");
		p->age = i+1;

		setElement(arr, i, p); // arr[i] = i+1;
	}

	for(i = 0; i < getCapacity(arr); i++)
	{
		p = (PERSON*)getElement(arr, i);
		printf("arr[%d] = %s, %d\n", i, p->name, p->age);
	}


	// printf("sum = %d\n", sum_arr(arr));

	//for(i = 0; i< getCapacity(arr); i++)
	//	printf("arr[%d] = %d\n", i, getElement(arr, i));	// printf("arr[%d] = %d\n", i, arr[i]);
}

// append 기능 추가
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct __Array
{
	int capacity;
	int size;	//배열의 현재 크기
	void **content;

} Array;

Array* createArray(int capacity)
{
	Array *arr = (Array*)calloc(1, sizeof(struct __Array));
	arr->content = (void**)calloc(capacity, sizeof(void*));
	arr->capacity = capacity;

	return arr;
}

void* setElement(Array *arr, int index, void *pointer)
{
	void *old;
	int capacity = arr->capacity;
	if(index < 0 || index >= capacity)
	{
		fprintf(stderr, "out of index");
		exit(-1);
	}


	old = arr->content[index];	// backup
	arr->content[index] = pointer;
	return old;
}

int addElement(Array *arr, void *pointer) {
	int size = arr->size;
	int capacity = arr->capacity;

	if(size == capacity)
		return -1;

	arr->content[size] = pointer;
	arr->size++;

	return 0;
}

void* getElement(Array *arr, int index)
{
	int capacity = arr->capacity;
	if(index < 0 || index > capacity)
	{
		fprintf(stderr, "out of index");
		exit(-1);
	}

	return arr->content[index];
}

int getCapacity(Array *arr) { return arr->capacity; }
int getSize(Array *arr) {return arr->size; }

typedef struct
{
	char name[32];
	int  age;
} PERSON;

void display(Array *arr){
	PERSON *p;
	int i;

	system("cls");
	for(i=0;i<getSize(arr);i++){
		p = (PERSON*)getElement(arr, i);
		printf("arr[%d] = %s, %d\n", i, p->name, p->age);
	}
	getchar();
}

void main()
{
	int i;
	PERSON *p;
	Array *arr = createArray(5);

	display(arr);
	for(i = 0; i < getCapacity(arr); i++)
	{
		p = (PERSON*)malloc(sizeof(PERSON));
		strcpy(p->name, "kkk");
		p->age = i+1;

		addElement(arr, p);

		display(arr);
	}

	for(i = 0; i < getCapacity(arr); i++)
	{
		p = (PERSON*)getElement(arr, i);
		printf("arr[%d] = %s, %d\n", i, p->name, p->age);
	}
}



1.c

2.c

3.c



Posted by 밍쫑
,