'잡다한것들전부'에 해당되는 글 207건
- 2014.01.16 [펌] 유니티 엔진 팁 - GUI시스템
- 2014.01.16 [디버깅] Cocos2dx 이클립에서 안드로이드 네이티브 디버깅
- 2014.01.15 c언어 공부할때 참고 사이트
- 2014.01.15 관련 자료
- 2014.01.14 [Box2D] Box2D 기본 예제 디버그 모드 및 스프라이트 생성
- 2014.01.14 cocos2d-x 멀티 터치 처리하기
- 2014.01.14 Box2d 사용시(처음에 시작시 체크하지 않았을시)
- 2014.01.13 [펌][자료구조] 연결리스트 (Linked List) - 개념과 구현
- 2014.01.13 [펌]C언어 자료구조 - 연결리스트(Linked List)
- 2014.01.13 [펌] 단순연결리스트(Single Linked List) 예제
이번에 유니티 엔진으로 아이폰/안드로이드 게임을 개발하면서 겪었던 문제점 및 해결방법들 입니다. 특별한게 있는건 아니지만 공유하는 측면에서 올려보겠습니다~ 1. 유니티 GUI시스템. 유니티를 쓰는 사람들의 말을 들어보면 Unity3D의 기본적인 GUI는 가급적 사용하지 말것을 권장하고 있습니다. 빈 OnGUI함수조차도 성능을 저하시킨다고 하네요. 저희 프로젝트에서는 EzGUI라는 써드파티 라이브러리를 구입하여 사용했습니다. 장점으로는... - UI이미지들을 텍스쳐 아틀라스(atlas)로 만들어서 좌표를 따다 쓰는 방식이라, 한번의 drawcall로 모든 UI가 그려지기 때문에 성능이 좋음. - 디자이너가 작업시 위지윅 방식이 가능함(에디터내에서 직접 보면서 배치할 수 있음). 단점은... - 스킨시스템은 지원 안됨(모서리만 따서 늘려쓴다던가 하는 방식). - atlas(아틀라스:텍스쳐들을 모아놓은 하나의 큰 텍스쳐)를 만들때 이미지 배치가 수시로 바뀜. 어차피 uv좌표를 직접 입력하진 않기 때문에 문제는 없지만 웬지 개운하지 않음. 특시 prefab과 연결시켜 놓으면 값이 꼬이는 문제가 발생하여서 연결을 끊고 atlas를 만들어야 해서 번거로움이 심했음. (이 부분은 저희가 잘못 사용한것일지도 모르겠습니다. 정식 강좌를 본것이 아니라 인터넷에서 그때그때 찾아 한 것이라^^) - 업데이트 소식이 없음. 디자이너와의 분업 측면 - 디자이너가 레이아웃을 잡고, prefab으로 만든 후 패키징 하여 프로그래머에게 전달하여 작업함. 큰 무리는 없었지만 Unity3D에디터에 캐시파일이 남아서 인지, 가끔 종료한 후 다시 열어줘야 새로운 내용이 적용되었음. - 공식 사이트나 포럼에서도 분업에 대한 정확한 메뉴얼을 찾지 못하여 이 방식이 올바른것인지는 애매하였음. - 공동작업에 대한 고려가 많이 부족하다는 느낌을 받음. 해상도 작업 - 기본적으로 여러 해상도에 대한 지원이 부족한듯 함. - 화면 크기가 바뀌었을때 이미지 스케일이 원하는 대로 나오지 않았기 때문에 직접 로직을 작성하였음. - 안드로이드에서 가장 많이 사용하는 480*800을 기준으로 이미지작업을 하고, 화면 세로 크기의 비율을 구해서 모든 UI오브젝트들의 스케일에 적용시켜주었음. - 일부UI 컨트롤에는 적용시키지 말아야 할 경우도 생김 (예를 들면 슬라이더바같은 경우 바와 knob으로 구성되는데 부모-자식 관계에 있다보니 스케일이 이중으로 적용되어서 의도한것과 다르게 나타났다. 따라서 이런 경우에는 자식 오브젝트들의 스케일 적용은 건너뛰는 루틴을 넣어야 했다). 폰트작업 - BMFont라는 툴로 ttf파일에서 텍스쳐와 좌표값을 뽑아낸 뒤 불러다 쓰는 방식임. - 한글 입/출력은 잘 됨. - 폰트 색상 조절은 원하는 컬러의 material을 만들어서 사용하는 방식이며, 크기 조절은 오브젝트의 스케일값으로 조절이 가능함. * 다음프로젝트에는 NGUI를 사용할 예정입니다~ |
'잡다한것들전부 > 팁' 카테고리의 다른 글
| [펌] 유니티 엔진 팁 - 로딩시간 최적화에 대해서 (0) | 2014.01.16 |
|---|---|
| [펌] 유니티 엔진 팁 - 비동기 로딩 흉내내기 (0) | 2014.01.16 |
| [펌] 유니티 엔진 팁 - GUI시스템 (0) | 2014.01.16 |
| [함수] 유니티 함수 Vector3.Lerp에 대해서 알아보자. (0) | 2014.01.12 |
| 유니티 Vector3 를 상수 선언 하고 싶을때. (0) | 2014.01.09 |
| [펌][C# 강좌] 직접 만들어보는 메모리 풀 클래스 (0) | 2014.01.05 |
|
'잡다한것들전부 > 팁' 카테고리의 다른 글
| 공부하고 싶은 것들 정리.(구글킵) (0) | 2014.07.30 |
|---|---|
| [디버깅] Cocos2dx 이클립에서 안드로이드 네이티브 디버깅 (0) | 2014.01.16 |
| cocos2d-x 멀티 터치 처리하기 (0) | 2014.01.14 |
| autoRelease 및 retain() , release(), retainCount() (0) | 2014.01.13 |
| CCNode 및 CCArray 의 메모리 관리 (0) | 2014.01.13 |
| cocos2d-x multi-resolution (0) | 2014.01.13 |
http://www.soen.kr
'잡다한것들전부 > C, C++, C#' 카테고리의 다른 글
| c++ 책을 샀습니다. (0) | 2014.08.04 |
|---|---|
| c# 표준 코딩 규칙 (0) | 2014.07.24 |
| c언어 공부할때 참고 사이트 (0) | 2014.01.15 |
| [펌]C언어 자료구조 - 연결리스트(Linked List) (0) | 2014.01.13 |
| [펌] 단순연결리스트(Single Linked List) 예제 (0) | 2014.01.13 |
| c++에서 bool 형 값 true false 실수할 수 있는 부분 (0) | 2014.01.13 |
http://www.raywenderlich.com
'잡다한것들전부 > 2D 관련 자료' 카테고리의 다른 글
| 유니티 2디 간단 사용영상 (0) | 2014.01.22 |
|---|---|
| 관련 자료 (0) | 2014.01.15 |
전체소스
#ifndef __CH4_BASICSETUP__
#define __CH4_BASICSETUP__
#include "cocos2d.h"
#include "Recipe.h"
#include "Box2D/Box2D.h"
#include <GLES-Render.h>
//32 픽셀 = 1미터
#define PTM_RATIO 32
class Ch4_BasicSetup : public Recipe
{
private:
b2World* world;
GLESDebugDraw *m_debugDraw;
public:
virtual CCLayer* runRecipe();
void addLevelBoundaries();
void step(float dt);
virtual void draw();
void addNewSpriteWithCoords(CCPoint p);
void ccTouchesEnded(CCSet * touches, CCEvent * event);
};
CCLayer* Ch4_BasicSetup::runRecipe()
{
Recipe::runRecipe();
this->setTouchEnabled(true);
/* Box2D 초기화 */
// 중력의 방향을 결정한다.
b2Vec2 gravity = b2Vec2(0.0f, -30.0f);
// 월드를 생성한다.
world = new b2World(gravity);
world->SetAllowSleeping(true);
world->SetContinuousPhysics(true);
//디버그 드로잉 초기화
m_debugDraw = new GLESDebugDraw( PTM_RATIO );
world->SetDebugDraw(m_debugDraw);
uint32 flags = 0;
flags += b2Draw::e_shapeBit;
m_debugDraw->SetFlags(flags);
//레벨 경계 생성
this->addLevelBoundaries();
//블록생성을 위한 배치 노드 생성
CCSpriteBatchNode *batch = CCSpriteBatchNode::create("blocks.png", 150);
this->addChild(batch, 0, 0);
//새로운 블록 추가
CCSize screenSize = CCDirector::sharedDirector()->getWinSize();
this->addNewSpriteWithCoords(ccp(screenSize.width/2, screenSize.height/2));
//스텝 메서드 스케줄링
this->schedule(schedule_selector(Ch4_BasicSetup::step));
return this;
}
//양쪽 사각형 영역 설정
void Ch4_BasicSetup::addLevelBoundaries()
{
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
// 가장자리(테두리)를 지정해 공간(Ground Box)을 만든다.
// 바디데프에 좌표를 설정한다.
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0,0);
// 월드에 바디데프의 정보(좌표)로 바디를 만든다.
b2Body *groundBody = world->CreateBody(&groundBodyDef);
// 가장자리(테두리) 경계선을 그릴 수 있는 모양의 객체를 만든다.
b2EdgeShape groundEdge;
b2FixtureDef boxShapeDef;
boxShapeDef.shape = &groundEdge;
// 에지 모양의 객체에 Set(점1 , 점2)으로 선을 만든다.
// 그리고 바디(groundBody)에 쉐이프(groundEdge)를 고정시킨다.
// 아래쪽
groundEdge.Set(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0));
groundBody->CreateFixture(&boxShapeDef);
// 왼쪽
groundEdge.Set(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO));
groundBody->CreateFixture(&boxShapeDef);
// 위쪽
groundEdge.Set(b2Vec2(0, winSize.height/PTM_RATIO),
b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO));
groundBody->CreateFixture(&boxShapeDef);
// 오른쪽
groundEdge.Set(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO),
b2Vec2(winSize.width/PTM_RATIO, 0));
groundBody->CreateFixture(&boxShapeDef);
}
//물리적 위치를 이용해서 그래픽 위치를 갱신
void Ch4_BasicSetup::step( float dt )
{
int32 velocityIterations = 8;
int32 positionIterations = 3;
world->Step(dt, velocityIterations, positionIterations);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL) {
CCSprite *obj = (CCSprite*)b->GetUserData();
obj->setPosition( CCPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );
obj->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
}
}
}
/* 디버그 그리기 데이터 */
void Ch4_BasicSetup::draw()
{
//텍스쳐 비활성화
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
world->DrawDebugData();
//텍스쳐 재활성화
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
/* 텍스처 입힌 블록을 추가합니다. */
void Ch4_BasicSetup::addNewSpriteWithCoords( CCPoint p )
{
CCSpriteBatchNode *batch = (CCSpriteBatchNode*) this->getChildByTag(0);
//랜덤하게 텍스쳐 처리된 블록을 생성
int idx = (CCRANDOM_0_1() > .5 ? 0:1);
int idy = (CCRANDOM_0_1() > .5 ? 0:1);
CCSprite *sprite = CCSprite::createWithTexture(batch->getTexture(), CCRectMake(32 * idx,32 * idy,32,32));
batch->addChild(sprite);
sprite->setPosition(ccp( p.x, p.y));
//물체 정의 및 생성
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
bodyDef.userData = sprite;
b2Body *body = world->CreateBody(&bodyDef);
//동적 본체를 위한 또다른 상자 모양 정의
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(.5f, .5f);//1m 상자의 중간 지점
//동적 물체 픽스쳐 정의.
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
body->CreateFixture(&fixtureDef);
}
//클릭시 물체 추가 생성
void Ch4_BasicSetup::ccTouchesEnded( CCSet * touches, CCEvent * event )
{
//멀티터치 처리
CCSetIterator it = touches->begin();
CCTouch* touch;
for( int iTouchCount = 0; iTouchCount < touches->count(); iTouchCount++ )
{
touch = (CCTouch*)(*it);
CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
this->addNewSpriteWithCoords(location);
it++;
}
}
#endif
'잡다한것들전부 > cookbook관련' 카테고리의 다른 글
| [Box2D] Box2D 기본 예제 디버그 모드 및 스프라이트 생성 (0) | 2014.01.14 |
|---|---|
| Box2d 사용시(처음에 시작시 체크하지 않았을시) (0) | 2014.01.14 |
void HelloWorld::ccTouchesEnded( CCSet * touches, CCEvent * event )
{
//멀티터치 처리
CCSetIterator it = touches->begin();
CCTouch* touch;
for( int iTouchCount = 0; iTouchCount < touches->count(); iTouchCount++ )
{
touch = (CCTouch*)(*it);
CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
it++;
}
}
'잡다한것들전부 > 팁' 카테고리의 다른 글
| 공부하고 싶은 것들 정리.(구글킵) (0) | 2014.07.30 |
|---|---|
| [디버깅] Cocos2dx 이클립에서 안드로이드 네이티브 디버깅 (0) | 2014.01.16 |
| cocos2d-x 멀티 터치 처리하기 (0) | 2014.01.14 |
| autoRelease 및 retain() , release(), retainCount() (0) | 2014.01.13 |
| CCNode 및 CCArray 의 메모리 관리 (0) | 2014.01.13 |
| cocos2d-x multi-resolution (0) | 2014.01.13 |
처음 프로젝트를 생성할때 Box2d 를 선택하지 않고 프로젝트를 만들면
각종 오류들이뜸
속성-링커-입력-추가종속성- libBox2d.lib추가
속성-c/c++-추가포함디렉터리 - $(SolutionDir)external 추가
하면 대강 오류는 없어짐
'잡다한것들전부 > cookbook관련' 카테고리의 다른 글
| [Box2D] Box2D 기본 예제 디버그 모드 및 스프라이트 생성 (0) | 2014.01.14 |
|---|---|
| Box2d 사용시(처음에 시작시 체크하지 않았을시) (0) | 2014.01.14 |
출처 : http://blog.naver.com/PostView.nhn?blogId=keloc&logNo=40154090761
지난 시간에는 스택과 큐의 개념과 배열로 각각 구현을 해봤습니다. 이번에 살펴 볼 연결리스트(Linked List)는 정적인 배열과 달리 동적인 자료구조로 필요한 경우 할당하여 사용하고 필요가 없어지면 해제하는 식으로 메모리 관리가 가능하기 때문에 메모리를 절약할 수 있다는 장점이 있습니다.

[연결리스트의 기본구조 : 단순 연결리스트]
연결리스트(링크드리스트 : Linked List)의 개념
연결리스트는 노드(Node)와 링크(Link)로 구성되며, 노드는 실제 정보를 담고 있는 하나의 단위이고, 링크는 노드간의 위치정보를 저장하고 있어 연결리스트의 순서를 유지할 수 있도록 하는 연결고리로 이해 하시면 됩니다.
연결리스트는 각 노드별 링크의 개수와 연결 상태에 따라 다양한 형태로 구성 될 수 있는데요. 단순 연결리스트, 환형 연결리스트, 이중 연결리스트, 이중 환형 연결리스트 등으로 나눌 수 있습니다.
단순 연결리스트 (Simple Linked List)
단순 연결리스트는 위 그림과 같이 선형적으로 한방향인 리스트의 형태로서 가장 많이 쓰이는 형태입니다. 여기서 리스트의 시작과 끝을 가리키는 노드가 필요한데요, 각각 머리(Head)와 꼬리(Tail)이라는 이름의 노드로 항상 존재하게 됩니다.
앞서 본 선형 구조의 자료구조인 스택과 큐에서처럼 연결리스트에도 노드의 추가, 삭제, 탐색 등의 연산이 있습니다. 여기서는 각각을 insert, delete, find라고 부르겠습니다.
0. 노드 정의
연결리스트의 노드는 단순히 정수형 데이터 하나만 가진다고 가정하고, 다음과 같이 정의 할 수 있습니다.
typedef struct _node{
int key;
struct _node *next;
}node;
초보자들은 구조체 정의에 _node의 포인터에 당황하실지도 모르겠습니다만, 구조체에서 이런 재귀 정의는 가능하며, 이 의미는 _node라는 구조체 타입을 가리키는 포인터 즉, 다음 노드를 가리킨다는 사실을 아셔야 합니다.
1. 연결리스트 초기화
연결리스트의 초기상태는 머리(이하 Head)와 꼬리(이하 Tail)가 연결된 형태로 다음과 같은 모양을 가지고 있습니다.

[빈 연결리스트]
위와 같이 연결리스트가 비어 있을 경우는 Head가 Tail을 Tail은 그 자신을 가리키는 형태가 되어 있어야 합니다.
node *head, *tail;
void init_list (void) {
head = (node *)malloc(sizeof(node));
tail = (node *)malloc(sizeof(node));
head->next = tail;
tail->next = tail;
}
2. 연결리스트의 노드추가 - 삽입 : insert_next
연결리스트의 삽입(이하 insert)은 다음과 같은 순서로 진행됩니다.

(가) 초기 모양 (t는 head를 가리킴)

(나) L node를 생성합니다. (s가 가리킴)

(다) L node가 t의 다음 node를 가리킵니다. (s->next = t->next)

(라) t의 다음 node 를 L node로 로 변경합니다. (t->next=s)
위와 같은 과정을 구현하면 다음과 같습니다.
node *insert_next (int key, node *t) {
node *s;
s = (node *)malloc(sizeof(node));
s->key = key;
s->next = t->next;
t->next = s;
return s;
}
3. 연결리스트의 노드삭제 - delete_next
연결리스트의 삭제(이하 delete)는 다음과 같은 순서로 진행됩니다.

(가) 초기상태 (삭제 전 Node를 t가 가리킴)

(나) 삭제 대상 Node에 임시 포인터 (s= t->next)

(다) 삭제 전 Node의 다음 포인터 (t->next = t->next->next)

(라) 삭제 대상 노드 해제 (free(s))
코드로 구현하면,,,
int delete_next (node *t) {
node *s;
if (t->next == tail)
return 0;
s = t->next; // (나)
t->next = t->next->next; // (다)
free(s); // (라)
return 1;
}
4. 연결리스트 Node 검색 : find
위와 같이 특정한 key의 다음 Node에 연산을 위해서는 Node를 찾는 연산이 필요한데요. 이는 Head에서 Tail까지 주어진 key가 맞는지 확인 후 return해 주면 됩니다. 바로 코드를 볼께요.
node *find_node (int key) {
node *s;
s = head->next; // head->next가 연결리스트의 첫 node
while (s->key != key && s != tail) // 찾는 key가 맞거나 tail이면 끝
s = s->next; // 다음 node로
return s;
}
find_node함수의 return값을 보고 tail이면 검색에 실패, 아니면 성공입니다. 쉽죠?
연결리스트의 개념을 이해할 때, Node를 그려가면서 연산(insert, delete)을 직접 손으로 해보는게 좋습니다. 주의할 점은 링크의 연결과 제거 그리고 Node의 메모리 해제의 순서가 달라지면 링크가 끊어져 버리는 오류가 발생할 수 있습니다.
예를 들어 다음과 같은 경우를 보죠.
(가) insert 하려는 s node를 다음 node에 먼저 연결하지 않은 경우

(나) 삭제하려는 Node s의 메모리를 먼저 해제한 경우

이와 같은 실수를 하지 않도록 주의 하시길 바라면서 연결리스트(단순연결리스트)에 대한 설명을 마치겠습니다.
다음시간에는 환형연결리스트와 이중연결리스트에 대해서 알아보겠습니다.
[출처] [자료구조] 연결리스트 (Linked List) - 개념과 구현|작성자 keloc
'잡다한것들전부 > 기타' 카테고리의 다른 글
| MS Word 당구장 표시 (0) | 2014.01.17 |
|---|---|
| 맥에서 스크린샷 캡쳐하기 (0) | 2014.01.17 |
| [펌][자료구조] 연결리스트 (Linked List) - 개념과 구현 (0) | 2014.01.13 |
| [펌] A* 알고리즘 (A Star Algorithm ) (0) | 2014.01.13 |
| 길찾기 알고리즘 소스들 (0) | 2014.01.13 |
| [펌] 초보자를 위한 A* 알고리즘 (기초개념 설명 및 소스) (0) | 2014.01.13 |
오늘은 C언어 연결리스트에 대해서 포스팅을 해보려고 한다.
내가 자료구조라는 것을 처음 접한 대학교 2학년 때 난 이 연결리스트라는 놈을 도저히 이해할 수가 없었다.
왜 이놈들은 함수가 끝나도 계속 메모리에 남아있는 걸까? 라는게 가장 큰 의문점이었고
두번째는 그냥 적당한 라이브러리 쓰면 되는데 왜 굳이 이런걸 만들어야 하는걸까?
라는게 두번째 의문점이었다.
첫번째 의문점은 후에 "다시 체계적으로 배우는 C언어 포인터" 라는 책을 정독한 후에 풀렸고
두번째 의문점은.. 아직도 미스테리다.
다만 우리가 전산학과 학생으로서 이런 것들을 구현해보고 원리를 파악할 수 있다는 이유로 대충 이해하고 넘어가자.
사족이 길었는데..
연결리스트란 무엇인가?
리스트는 자료를 순차적으로 정리해놓은 것을 말한다.
이것들이 메모리상에서 연결되어 있다는 뜻이다.
배열 리스트 같은 경우 리스트의 크기를 미리 크게 정해놓고 그 범위 안에서만 자료의 관리가 가능하기 때문에
메모리 낭비가 심하다고 볼수 있는데
연결리스트의 경우는 자료가 입력 될 때마다 동적할당으로 새로운 메모리 주소에 값을 할당하고
이전 자료와 연결해주기 때문에 메모리 관리가 용이하다.
자료 하나를 담고있는 녀석을 보통 "노드(node)" 라고 부른다.
연결 리스트에 아무것도 없는 상태에서 100이라는 값을 가진 노드를 추가한다고 생각해보자.
노드는 자기 자신의 값과 다음 노드를 가리키는 노드 포인터로 구성된다.
여기서 첫번째 노드는 100이라는 값을 갖고 있으며 다음 노드는 없으므로 NULL 포인터를 가리킨다.
위에 Head라는 노드포인터도 있는데 이것은 연결리스트라는 자료구조에서 일종의 시작점을 알려준다.
배열 리스트 처럼 인덱스를 이용한 간편한 접근이 불가능하므로 첫 노드를 Head 포인터로 가르켜주고
그 Head 포인터를 이용해 다음 노드, 다음 노드 이런 식으로 다른 노드에 접근할 수 있다.
101이라는 값을 갖고 있는 두번째 노드를 삽입하면 이렇게 된다. (과정은 잠시 후에 설명)
기존에 NULL 포인터를 가리키고 있던 첫번째 노드(100이라는 값을 가진 노드)는 이제 다음 노드로 새로 추가된 노드를 가리키고 두번째이자 마지막 노드가 된 101이라는 값을 가진 노드는 다음 노드로 NULL 포인터를 가리킨다.
연결 리스트는 이와 같은 구조로 자료들을 쭈욱 연결해서 저장한다.
그럼 이제 100 노드와 101 노드 사이에 200이라는 값을 가진 노드를 삽입해보자.
우선 동적할당으로 노드 하나를 만들어주고 200이라는 값을 넣어준다.
이 노드의 다음 노드는 원래 100 노드가 다음 노드로 가리키던 노드를 가리키도록 해준 다음
100노드의 다음 노드를 200 노드로 설정하면 깔끔하게 삽입된다.
나도 공대생 인지라.. 이런 복잡한 그림보다 코드를 보는게 이해가 빠를것 같아서..
설명은 여기까지.
아래는 struct 와 함수 선언부분이다. (헤더파일로 쓸 수 있음)
node 는 정수형인 value 와 node*(노드포인터) 형인 next 라는 변수를 갖고 있다.
이 코드에서 우리는 node 보다는 node pointer를 많이 쓸것이므로 typedef를 이용해 nptr을 지정해줬다.
그다음은 list라는 struct를 정해서 head를 가리키는 노드포인터와 리스트에에 몇개의 노드가 있는지 알려주는 count라는 변수를 만들었다.
그 아래쪽 함수는 생각하는 그대로다. (순서대로 초기화, 삽입, 삭제, 검색, 수정, 출력)
연결 리스트 초기화 함수이다.
메인 함수에서 list를 만들고 그 주소를 init()에 넘겨주어 count와 head를 초기화시킨다.
노드 삽입 함수. 리스트형 포인터 변수와 값, 위치를 인수로 받는다.
처음 if 문은 position 값이 적절한지 체크하는 부분이다. 부적절하면 메시지를 출력하고 종료한다.
다음은 new_nptr 이라는 노드포인터에 node 사이즈만큼의 메모리를 동적할당하고 value변수를 설정해준다.
position이 1인 경우 head포인터가 바뀌어야 하므로 첫부분에서 따로 처리해줬고
그게 아닌 경우는 head 포인터의 값을 tmp라는 변수에 복사해서 for 문을 이용해 의도한 위치에 도달할 때까지 계속 next로 찾아간다.
적정 위치에 도달하면 삽입한 후 리스트의 카운터를 1 증가시킨다.
삭제 함수. 리스트형 포인터변수와 위치를 인수로 받는다.
첫부분은 삽입과 마찬가지로 position의 처리 가능 범위를 체크한다. (단, 삽입의 경우 맨 뒤에도 삽입 가능하기 때문에 기존에 존재하는 노드들의 position만 받아야 하는 삭제 함수와는 범위가 1 차이 난다.)
삽입과 마찬가지로 head 포인터를 tmp로 받아준 다음 position이 1이면 head 노드를 바꿔주고 그게 아니라면 position 변수를 이용해 그 위치로 찾아가서 해당 노드의 연결을 해지시킨다.
삭제될 노드의 앞 노드를 tmp로 받고 그 다음 노드를 tmp2로 받아서 tmp2의 다음노드가 tmp의 다음 노드가 되도록 짰다.
삭제에서 주의할 점은 삭제된 노드가 메모리에서 지워질 수 있도록 free() 함수를 이용해줘야 한다는 것이다.
(이때문에 굳이 tmp2라는 노드 포인터 변수를 선언했다.)
검색 함수. 리스트형 포인터 변수와 값을 인수로 받는다.
값을 입력받아서 리스트를 순회하여 같은 값이 있는지 알아본다.
같은 값이 여러개 있다면 처음 나온 position을 리턴하고 없으면 0을 리턴한다.
테스트를 위해 적절한 printf() 함수를 사용했다.
수정 함수. 리스트형 포인터 변수와 값, 위치를 인수로 받는다.
삽입, 삭제와 비슷한데 다른 점은 head 포인터를 변경할 필요가 없다는 것이다.
해당 위치의 노드만 찾아서 값을 바꿔주면 된다.
출력 함수. 리스트형 포인터 변수를 인수로 받는다.
이건 테스트를 위해 만들어본 함수다.
리스트에 들어있는 값들과 count 값을 출력해준다.
메인 함수.
리스트형 포인터변수에 리스트 크기의 메모리를 동적할당 해주고 init(() 함수를 이용해 초기화시켜준다.
저 뒤에 여러가지 테스트 한다고 끄적거려 논거 있는데 너무 길어서 여기까지만 캡쳐.
그래서 뒤에 } 로 닫아줘야 함.
출처 : http://milvus.tistory.com/17
소스코드
/*
* linkedlist.c
*
* Created on: 2011. 4. 21.
* Author: Chwang
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct _node{
int value;
struct _node* next;
}node;
typedef node* nptr;
typedef struct _list{
int count;
nptr head;
}list;
void init(list* lptr);
void insert(list* lptr,int value,int position);
void delete(list* lptr,int position);
int search(list* lptr,int value);
void modify(list* lptr,int value,int position);
void print_list(list* lptr);
void init(list* lptr){
//initialize the list
lptr->count=0;
lptr->head=NULL;
}
void insert(list* lptr,int value,int position){
//insert value to proper position
if(position<1 || position>(lptr->count)+1){
printf("Position Out of Bound\n");
return;
}
nptr new_nptr=(node*)malloc(sizeof(node));
new_nptr->value=value;
if(position==1){
new_nptr->next=lptr->head;
lptr->head=new_nptr;
}
else{
nptr tmp=lptr->head;
int i;
for(i=1;i<position-1;i++){
tmp=tmp->next;
}
new_nptr->next=tmp->next;
tmp->next=new_nptr;
}
lptr->count++;
}
void delete(list* lptr,int position){
//delete an item on the position
if(position<1 || position>(lptr->count)){
printf("Position Out of Bound\n");
return;
}
nptr tmp=lptr->head;
if(position==1){
lptr->head=tmp->next;
free(tmp);
}
else{
int i;
for(i=1;i<position-1;i++){
tmp=tmp->next;
}
nptr tmp2=tmp->next;
tmp->next=tmp2->next;
free(tmp2);
}
lptr->count--;
}
int search(list* lptr,int value){
//traverse the list and
//find the first position of the value (first from head)
//if not exist, return 0
nptr tmp=lptr->head;
int i=1;
while(tmp!=NULL){
if(value==tmp->value) break;
i++;
tmp=tmp->next;
}
if(i>lptr->count){
printf("The value %d is NOT exists\n",value);
return 0;
}
else{
printf("The value %d is at position %d in the list\n",value,i);
return i;
}
}
void modify(list* lptr,int value,int position){
if(position<1 || position>(lptr->count)){
printf("Position Out of Bound\n");
return;
}
nptr tmp=lptr->head;
int i;
for(i=1;i<position;i++){
tmp=tmp->next;
}
tmp->value=value;
}
void print_list(list* lptr){
nptr tmp=lptr->head;
printf("List value: ");
while(tmp!=NULL){
printf("%d ",tmp->value);
tmp=tmp->next;
}
printf("\n");
printf("Total: %d value(s)\n",lptr->count);
}
int main(){
list* mylist=(list*)malloc(sizeof(list));
init(mylist);
insert(mylist,3,1);
insert(mylist,4,2);
insert(mylist,5,3);
insert(mylist,6,4);
insert(mylist,7,5);
insert(mylist,8,6);
insert(mylist,9,7);
insert(mylist,3,3);
print_list(mylist);
delete(mylist,3);
delete(mylist,5);
print_list(mylist);
search(mylist,6);
search(mylist,9);
search(mylist,0);
modify(mylist,100,1);
modify(mylist,101,2);
print_list(mylist);
return 0;
}
'잡다한것들전부 > C, C++, C#' 카테고리의 다른 글
| c# 표준 코딩 규칙 (0) | 2014.07.24 |
|---|---|
| c언어 공부할때 참고 사이트 (0) | 2014.01.15 |
| [펌]C언어 자료구조 - 연결리스트(Linked List) (0) | 2014.01.13 |
| [펌] 단순연결리스트(Single Linked List) 예제 (0) | 2014.01.13 |
| c++에서 bool 형 값 true false 실수할 수 있는 부분 (0) | 2014.01.13 |
| 동기화 비동기화 동기식 비동기식 이란? (0) | 2014.01.13 |
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <time.h>
typedef struct tagNode
{
int data;
struct tagNode *next;
} NODE;
NODE *head, *tail, *working;
// 리스트초기화
void InitList();
// 데이타하나추가
void Insert(int n);
// 주어진데이타를삭제
void Delete(int n);
// 데이타를모두삭제
void RemoveAll();
// 현재리스트의값들을모두더해서보여준다.
void AddAll();
// 주어진데이타와같은노드개수를카운트
int Count(int n);
// 현재리스트의모든내용을보여준다.
void DisplayList();
int main()
{
// 리스트초기화
InitList();
Insert(10);
Insert(20);
Insert(30);
Insert(40);
Insert(50);
Insert(10);
// Display 함수를이용하여연결리스트의데이터들을출력한다.
DisplayList();
// 전체합출력
AddAll();
// 데이타값이10 인노드의개수를카운트
Count(10);
// 노드삭제
Delete(10);
DisplayList();
Delete(50);
DisplayList();
Delete(20);
DisplayList();
RemoveAll();
return 0;
}
void InitList()
{
// 리스트초기화
head = NULL;
tail = NULL;
working = NULL;
}
void Insert(int n)
{
// 새로노드를하나만들어서값을대입
working = (NODE *)malloc(sizeof(NODE));
printf("Adding %d\n", n);
working->data = n;
// 이것이꼬리임
working->next = NULL;
// 만약머리가비었으면이것이머리임
if ( head == NULL )
{
head = working;
tail = working;
return;
}
// 머리가아니라면마지막에노드를삽입하고
tail->next = working;
// 이것이꼬리임
tail = working;
}
void Delete(int n)
{
// 아무런데이타도없으면
if ( head == NULL )
// 지울일도없다.
return;
// 일단머리를가져온다.
working = head;
NODE* node;
// 같은값을찾아서삭제
while ( working )
{
if ( working->data == n )
{
printf("Deleting %d...\n", working->data);
if ( working == head )
{
head = working->next;
delete working;
}
else
{
node->next = working->next;
delete working;
}
Delete(n); // 다른값이있으면또지움
break;
}
node = working;
working = working->next;
}
}
void RemoveAll()
{
// 머리를가져와서
working = head;
// 끝까지지움
while ( working )
{
NODE *node = working;
// 다음노드준비
working = working->next;
// 노드삭제
printf("Deleting %d\n", node->data);
free(node);
node = NULL;
}
InitList();
printf("All elements deleted.\n");
}
void AddAll()
{
int sum = 0;
working = head;
while ( working )
{
sum += working->data;
working = working->next;
}
printf("Sum of all : %d\n", sum);
}
int Count(int n)
{
int count = 0;
working = head;
while ( working )
{
if ( working->data == n )
++count;
working = working->next;
}
printf("Count of %d : %d\n", n, count);
return count;
}
void DisplayList()
{
printf("Display all element : ");
printf("head = ");
working = head;
while ( working )
{
printf("%d -> ", working->data);
working = working->next;
}
printf("= tail\n");
}출처 : http://blog.naver.com/PostView.nhn?blogId=xtelite&logNo=50086163288&redirect=Dlog&widgetTypeCall=true
'잡다한것들전부 > C, C++, C#' 카테고리의 다른 글
| c언어 공부할때 참고 사이트 (0) | 2014.01.15 |
|---|---|
| [펌]C언어 자료구조 - 연결리스트(Linked List) (0) | 2014.01.13 |
| [펌] 단순연결리스트(Single Linked List) 예제 (0) | 2014.01.13 |
| c++에서 bool 형 값 true false 실수할 수 있는 부분 (0) | 2014.01.13 |
| 동기화 비동기화 동기식 비동기식 이란? (0) | 2014.01.13 |
| 추상 클래스 (C++) (0) | 2014.01.10 |
RecipeCollection01.zip

