일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Java
- 네트워크
- spring webflux
- Algorithm
- 백준
- mongoDB
- OS
- design pattern
- 자바
- MSA
- JavaScript
- Galera Cluster
- redis
- 운영체제
- 디자인 패턴
- Kafka
- C
- Spring
- Heap
- 파이썬
- react
- 컴퓨터구조
- Proxy
- 알고리즘
- IT
- JPA
- 자료구조
- MySQL
- Data Structure
- c언어
- Today
- Total
시냅스
[자료구조] 연결리스트를 활용한 다항식 계산 구현 본문
다항식
다항식의 항은 계수 + 차수로 이뤄진다.
단 각 항은 내림차순 정렬로 가장 큰 차수가 header node가 된다.
정렬은 node를 생성하면서 조건문을 통해 앞이나 뒤에 넣을 수 있게 하였다.
단, 이 때 차수가 같은 노드가 추가되면 새로 node를 생성하지 않고 기존 Node에 연산만을 할 수 있게 하였다.
계산의 경우에는 덧셈 뺄셈과 곱셈 나눗셈을 따로 분리하여 생각하여야 한다.
덧셈, 뺄셈의 경우 같은 차수에서만 연산이 이뤄지면 되는데,
곱셈, 나눗셈의 경우에는 매 항마다 연산이 이뤄져야 한다.
또한 계수가 0일 경우에는 해당 항이 지워질 수 있게 하였다.
구현
- 리스트 생성
- 원소 추가
- 원소 반환
- 제거
- 연산
생성
typedef struct ListNodeType
{
int coef;
int degree;
struct ListNodeType *pLLink;
struct ListNodeType *pRLink;
} ListNode;
typedef struct LinkedListType
{
int currentElementCount; // 현재 저장된 원소의 개수
ListNode headerNode; // 헤더 노드(Header Node)
} LinkedList;
#include "polynomial.h"
LinkedList *createPolynomialList() // list를 생성한다.
{
LinkedList *lst;
lst = calloc(1, sizeof(LinkedList));
NULLCHECK(lst);
lst->currentElementCount = 0;
return (lst);
}
header에 이중 연결리스트를 선언하고,
list를 생성하여 반환한다.
추가
#include "polynomial.h"
int find_degree(LinkedList *pList, ListNode element) // 차수가 같은지 판별하여 더해준다.
{
ListNode *headNode;
int i;
headNode = pList->headerNode.pRLink->pLLink; // 뒤에서 부터 찾는다.
i = pList->currentElementCount;
while (i-- && !(headNode->degree == element.degree))
headNode = headNode->pLLink;
if (headNode->degree == element.degree) // 차수가 같다면
{
headNode->coef += element.coef; // 더해준다.
if (ZERO(headNode->coef))
removePLElement(pList, i);
return (TRUE);
}
return (FALSE);
}
int addPLElement(LinkedList *pList, ListNode element)
{
ListNode *newNode;
ListNode *headNode;
int i;
newNode = calloc(1, sizeof(ListNode));
newNode->coef = element.coef;
newNode->degree = element.degree;
if (ZERO(pList->currentElementCount)) { // header node 일 경우
pList->headerNode.pRLink = newNode; // header로 지정한다.
newNode->pLLink = pList->headerNode.pRLink; // 자기 자신을 지칭하게 한다.
newNode->pRLink = newNode;
}
else
{
if (find_degree(pList, element)) // 만약 같은 차수가 있다면, 기존 node에 더해준다.
{
free(newNode);
newNode = NULL;
return (TRUE);
}
i = 0;
headNode = pList->headerNode.pRLink->pLLink; // 뒤에서 부터 찾아준다.
while (IS_BIG(headNode->degree, newNode->degree))
// 새로 들어올 node의 차수가 더 작을 때 멈춰 차수로 정렬한다.
{
if (i++ == pList->currentElementCount) // while 문은 node 개수만큼만 반복한다.
break ;
headNode = headNode->pLLink;
}
newNode->pLLink = headNode; // 기존 list에 삽입한다.
newNode->pRLink = headNode->pRLink;
headNode->pRLink->pLLink = newNode;
headNode->pRLink = newNode;
headNode = &(pList->headerNode);
if (headNode->pRLink->pLLink->degree - headNode->pRLink->degree > 0)
// 만약 갱신된 node의 차수가 더 크다면 header를 갱신한다.
headNode->pRLink = headNode->pRLink->pLLink;
}
pList->currentElementCount++;
return (TRUE);
}
node를 추가하면서 find degree를 통해 같은 차수인지부터 판별하고,
만약 차수가 같다면 연산 이후 처리하지 않게 한다.
이후에는 while문을 통해 차수를 기준으로 내림차순 정렬할 수 있게 node를 추가하고
header를 갱신할 수 있게 한다.
반환
#include "polynomial.h"
ListNode *getPLElement(LinkedList* pList, int position) // 원하는 position의 node를 보여준다.
{
ListNode *head;
head = pList->headerNode.pRLink;
while (position)
{
head = head->pRLink;
position -= 1;
}
return (head);
}
원소 제거
#include "polynomial.h"
int removePLElement(LinkedList *pList, int position) // 개별 node 삭제
{
ListNode *headNode;
int i;
if (position < 0 || position >= pList->currentElementCount)
// position이 음수이거나, 현재 node 개수 이상일 수 없다.
return (FALSE);
i = 0;
headNode = pList->headerNode.pRLink;
while (i++ < position)
headNode = headNode->pRLink;
headNode->pLLink->pRLink = headNode->pRLink;
headNode->pRLink->pLLink = headNode->pLLink;
pList->currentElementCount--;
if (ZERO(position) && UPPER_ZERO(pList->currentElementCount)) // 만약 header node 라면
pList->headerNode.pRLink = headNode->pRLink; // header를 갱신한다.
headNode->pLLink = NULL;
headNode->pRLink = NULL;
free(headNode);
headNode = NULL;
return (TRUE);
}
header를 갱신하거나, 이전 이후 node를 잘 파악하여야 한다.
제거
#include "polynomial.h"
void clearPolynomialList(LinkedList *pList) // 내부 node를 전부 삭제한다.
{
ListNode *headNode;
ListNode *nextNode;
headNode = pList->headerNode.pRLink;
while (pList->currentElementCount)
{
nextNode = headNode->pRLink;
headNode->pLLink = NULL;
headNode->pRLink = NULL;
free(headNode);
headNode = nextNode;
pList->currentElementCount -= 1;
}
nextNode = NULL;
headNode = NULL;
}
#include "polynomial.h"
void deletePolynomialList(LinkedList *pList) // 내부 node와 list를 삭제한다.
{
clearPolynomialList(pList);
free(pList);
pList = NULL;
}
clear로 내부 node를 전부 삭제하고,
delete로 list까지 삭제한다.
덧셈, 뺄셈
#include "polynomial.h"
LinkedList *plus(LinkedList *aList, LinkedList *bList) // 다항식의 덧셈
{
LinkedList *newList = createPolynomialList();
alloc_calc_node(newList, aList, 0);
alloc_calc_node(newList, bList, 0);
return (newList);
}
#include "polynomial.h"
LinkedList *minus(LinkedList *aList, LinkedList *bList) // 다항식의 뺏셈
{
LinkedList *newList = createPolynomialList();
alloc_calc_node(newList, aList, 0);
alloc_calc_node(newList, bList, 1);
return (newList);
}
#include "polynomial.h"
void alloc_calc_node(LinkedList *new_list, LinkedList *base_list, int flag)
{
ListNode *base_head;
ListNode *new_node;
int baseidx = base_list->currentElementCount; // 연산을 위해 base list node 갯수를 저장한다.
base_head = base_list->headerNode.pRLink;
new_node = malloc(sizeof(ListNode));
while(baseidx--)
{
new_node->degree = base_head->degree;
if (flag)
new_node->coef = -(base_head->coef);
else
new_node->coef = base_head->coef;
addPLElement(new_list, *new_node); // node를 새로운 list에 할당한다.
base_head = base_head->pRLink;
}
free(new_node);
new_node = NULL;
deletePolynomialList(base_list);
base_list = NULL;
}
list를 새로 하나 생성하여 각 node들에 대한 연산을 해준다.
이 때 add를 통해 이미 같은 차수에 대한 고려는 하였기 때문에, add를 통한 node 생성만 고려하면 된다.
단 flag를 통하여 minus일 경우에는 뒤의 항에 -연산을 해줘 빼 줄 수 있게 한다.
나눗셈, 곱셈
#include "polynomial.h"
void alloc_calc_node(LinkedList *new_list, LinkedList *base_list, int flag)
{
ListNode *base_head;
ListNode *new_node;
int baseidx = base_list->currentElementCount; // 연산을 위해 base list node 갯수를 저장한다.
base_head = base_list->headerNode.pRLink;
new_node = malloc(sizeof(ListNode));
while(baseidx--)
{
new_node->degree = base_head->degree;
if (flag)
new_node->coef = -(base_head->coef);
else
new_node->coef = base_head->coef;
addPLElement(new_list, *new_node); // node를 새로운 list에 할당한다.
base_head = base_head->pRLink;
}
free(new_node);
new_node = NULL;
deletePolynomialList(base_list);
base_list = NULL;
}
#include "polynomial.h"
LinkedList *division(LinkedList *aList, LinkedList *bList) // 나눗셈 연산
{
int alen = getPolynomialListLength(aList) - 1;
int blen;
LinkedList *newList = createPolynomialList();
ListNode *newNode = calloc(1, sizeof(ListNode));
ListNode *aHeadNode = aList->headerNode.pRLink;
ListNode *bHeadNode;
while(alen--) {
blen = getPolynomialListLength(bList) - 1;
bHeadNode = bList->headerNode.pRLink;
while(blen--) {
newNode->coef = aHeadNode->coef / bHeadNode->coef; // 각 계수는 빼준다.
newNode->degree = aHeadNode->degree - bHeadNode->degree; // 각 차수는 나눠준다.
addPLElement(newList, *newNode);
bHeadNode = bHeadNode->pRLink;
}
aHeadNode = aHeadNode->pRLink;
}
deletePolynomialList(aList);
deletePolynomialList(bList);
aList = NULL;
bList = NULL;
return (newList);
}
나눗셈과 곱셈은 각 항마다 모든 연산이 이뤄져야 하기 때문에 2중 반복문을 통해 구현하였다.
덧셈, 뺄셈과 마찬가지로 add에서 연산 이외의 고려가 되어있기 때문에 해당 함수에서는 연산만을 처리한다.
'자료구조' 카테고리의 다른 글
[자료구조] 큐, Queue - 배열리스트로 구현 (0) | 2022.05.01 |
---|---|
[자료구조] 스택, Stack - 연결리스트(Linked list), 배열리스트(Array list)로 구현 (0) | 2022.04.25 |
[자료구조] List - 이중연결 리스트(Doubly Linked List) 구현 (0) | 2022.04.21 |
[자료구조] List - 원형 연결 리스트(Circular Linked List) 구현 (0) | 2022.04.21 |
[자료구조] List - 단일 연결 리스트(Singly Linked List) 구현 (0) | 2022.04.17 |