-
LinkedList(3) - 양방향 연결리스트자료구조와 알고리즘/자료구조 2023. 5. 2. 18:16
양방향 연결리스트는 노드에 양쪽을 연결해서 previous(이전) next(다음)을 통해 이동할 수 있는 리스트의 형태이다.
이전 노드를 가리키는 변수의 추가로 before를 통해 이전 노드를 기억해야하는 과정을 뺄 수 있다.
이전에 연결리스트 node에 previous를 가리킬 수 있는 변수만 추가해주면 된다.
-ADT
이전과 동일
단, 노드를 구현하는 부분 이전 노드를 가리키는 pre가 추가됨
typedef struct _node{Ldata data;struct _node* next;struct _node* pre;}node;-C 구현 (dummy기반 x)
>헤더파일
#ifndef _DB_LINKED_LIST#define _DB_LINKED_LIST
typedef int Ldata;
typedef struct _node{Ldata data;struct _node* next;struct _node* pre;}node;
typedef struct db_linked_list{node* head;node* cur;int size;}dblist;
typedef dblist List;
void Listinit(List* plist);void Linsert(List* plist, Ldata data);
int Lfirst(List* plist,Ldata* data);int LNext(List* plist,Ldata* data);int Lprevious(List* plist,Ldata* data);
int Lsize(List* plist);
#endif>소스파일
#include<stdio.h>#include<stdlib.h>#include"DB_LinkedList.h"
void Listinit(List* plist){plist->head = NULL;plist->cur =NULL;plist->size =0;}void Linsert(List* plist, Ldata data){//맨 앞에 데이터 추가 양 끝은 nullnode* newnode = (node*)malloc(sizeof(node));newnode->data = data;
newnode->next = plist->head; //처음에는 null, 다음부터는 있음if(plist->head != NULL){plist->head->pre = newnode;}newnode->pre = NULL;plist->head = newnode;(plist->size)++;}
int Lfirst(List* plist,Ldata* data){if(plist->head == NULL)return 0;plist->cur = plist->head;*data = plist->cur->data;return 1;}int LNext(List* plist,Ldata* data){if(plist->cur->next == NULL)return 0;
plist->cur = plist->cur->next;*data = plist->cur->data;return 1;}int Lprevious(List* plist,Ldata* data){if(plist->cur->pre == NULL) return 0;
plist->cur = plist->cur->pre;*data = plist->cur->data;return 1;}
int Lsize(List* plist){return plist->size;}새로운 데이터를 추가하는 과정만 조금 달라졌다.
>> 새로운 노드의 추가 (맨 앞에 데이터 추가)
1. newnode를 할당받고, 데이터 삽입 newnode의 next는 head를 가리킨다.
-1.1 head가 null이 아닐경우 head의 이전 노드를 newnode와 연결한다.
-1.2 head가 null일 경우 -> head에 이전 노드를 연결하지 않는다. head가 null이므로 다음 과정으로 head는 newnode가 되고, 양 끝은 null이 된다.
2. newnode의 pre에 null을 할당한다. 이는 맨 앞에 노드가 추가되는 것이고, 맨 왼쪽의 pre와 맨 오른쪽 next를 null로 만들기 위함이다.
3. head에 newnode를 할당
- dummy기반 C구현 (head와 tail 추가)
헤더파일
#ifndef _DB_liked_dummy#define _DB_liked_dummytypedef int Ldata;
typedef struct _node{Ldata data;struct _node* next;struct _node* pre;}node;
typedef struct db_linked_list_d{node* head;node* tail;node* cur;int size;}dblist_d;
typedef dblist_d List;
void Listinit(List* plist);void Linsert(List* plist, Ldata data);
int Lfirst(List* plist,Ldata* data);int LNext(List* plist,Ldata* data);int LPrivious(List* plist, Ldata* data);Ldata LRemove(List* plist);int Lsize(List* plist);
#endif소스파일
#include<stdio.h>#include<stdlib.h>#include"DB_linked.h"
void Listinit(List* plist){plist->head = (node*)malloc(sizeof(node));plist->head->pre = NULL;plist->head->next = plist->tail;
plist->tail = (node*)malloc(sizeof(node));plist->tail->pre=plist->head;plist->tail->next =NULL;plist->size =0;}void Linsert(List* plist, Ldata data){node* newnode = (node*)malloc(sizeof(node));newnode->data = data;newnode->next = plist->tail->pre->next; //초기에는 head->next인 tailnewnode->pre = plist->tail->pre; //초기에는 tail->pre인 headplist->tail->pre->next = newnode; //초기에는 head->next가 newnodeplist->tail->pre = newnode; //최근 이전노드를 newnode로 두기(plist->size)++;}
int Lfirst(List* plist,Ldata* data){if(plist->head->next == plist->tail) return 0;
plist->cur = plist->head->next;*data = plist->cur->data;return 1;}int LNext(List* plist,Ldata* data){if(plist->cur->next == plist->tail) return 0;plist->cur = plist->cur->next;*data =plist->cur->data;return 1;}int LPrivious(List* plist, Ldata* data){if(plist->cur->pre == plist->head) return 0;plist->cur = plist->cur->pre;*data =plist->cur->data;return 1;}Ldata LRemove(List* plist){node* Rnode = plist->cur;Ldata Rdata = Rnode->data;
plist->cur->pre->next = plist->cur->next;plist->cur->next->pre = plist->cur->pre;plist->cur = plist->cur->pre; //이거 빼먹을뻔!free(Rnode);(plist->size) --;return Rdata;}int Lsize(List* plist){
return plist->size;}> dummy ListInit
tail과 head를 추가하고 head->next = tail, tail->pre = head로 연결해둔다.
>dummy Insert
1. newnode에 data할당
2. newnode->next = tail->pre->next
>초기에는 tail->pre(next) ->next이므로 tail을 의미
> tail->pre가 newnode로 조정된 후에는 newnode->next의미 but 둘다 tail이긴하다.
3. newnode->pre = tail->pre
>초기에는 head의미
>tail->pre가 newnode로 조정된 후에는 이전 노드를 의미
4. tail->pre->next = newnode
>초기에는 head->next가 newnode가리킴
> tail->pre가 newnode로 조정되면, 이전노드의 next가 새 노드를 가리킴
5. tail->pre = newnode
>dummy remove
삭제할 노드 위치 cur
cur->pre->next = cur->next (이전 노드의 next를 현재 노드의 next와 연결)
cur->next->pre = cur->pre (앞 노드의 pre를 이전 노드와 연결)
cur = cur->pre 현재 노드의 위치도 이전 노드에 옮겨둠
->삭제할 노드의 연결 끊어지고 cur에 위치한 노드는 free로 메모리에서 제거하면 됨
'자료구조와 알고리즘 > 자료구조' 카테고리의 다른 글
스택의 활용 - 계산기 프로그램 (1) 2023.05.13 Stack - 배열,연결리스트,원형연결리스트 (0) 2023.05.04 LinkedList(3) 원형연결리스트 (1) 2023.05.02 LinkedList(2) - ADT와 구현 (0) 2023.05.01 LinkedList (1) (0) 2023.05.01