\(@^0^@)/

[TDL] 07/25 Today's-Done-List 본문

TDL

[TDL] 07/25 Today's-Done-List

minjuuu 2022. 7. 25. 23:02
728x90

- 유데미 알고리즘 이중 연결 리스트

사용 예시 : 데이터를 반대방향으로 취급해야 하는 경우, 검색 기록을 봐야 하는 경우

데이터를 검색할 때 이중 연결 리스트(DoublyLinkedList)는 단일 연결 리스트(SinglyLinkedList)에 비해 절반의 소요시간이 걸린다.

오늘은 get, set, insert, remove 메서드들을 살펴보았고, 아래는 지금까지 배운 이중 연결 리스트의 최종 코드이다.
내일부터는 문제를 풀어보며 더 깊이 이해해보자.

class Node {
	constructor(val) {
		this.val = val;
		this.next = null;
		this.prev = null;
	}
}

class DoublyLinkedList {
	constructor() {
		this.head = null;
		this.tail = null;
		this.length = 0;
	}
	push(val) {
		let newNode = new Node(val);
		if (this.length === 0) {
			this.head = newNode;
			this.tail = newNode;
		} else {
			this.tail.next = newNode;
			newNode.prev = this.tail;
			this.tail = newNode;
		}
		this.length++;
		return this;
	}
	unshift(val) {
		let newNode = new Node(val);
		if (this.length === 0) {
			this.head = newNode;
			this.tail = newNode;
		} else {
			this.head.prev = newNode;
			newNode.next = this.head;
			this.head = newNode;
		}
		this.length++;
		return this;
	}
	pop() {
		if (this.length === 0) return undefined;
		let poppedNode = this.tail;
		if (this.length === 1) {
			this.head = null;
			this.tail = null;
		} else {
			this.tail = poppedNode.prev;
			this.tail.next = null;
			poppedNode.prev = null;
		}
		this.length--;
		return poppedNode;
	}
	shift() {
		if (this.length === 0) return undefined;
		let oldHead = this.head;
		if (this.length === 1) {
			this.head = null;
			this.tail = null;
		} else {
			this.head = oldHead.next;
			this.head.prev = null;
			oldHead.next = null;
		}
		this.length--;
		return oldHead;
	}
	get(index) {
		if (index < 0 || index >= this.length) return null;
		let count, current;
		if (index <= this.length / 2) {
			count = 0;
			current = this.head;
			while (count !== index) {
				current = current.next;
				count++;
			}
		} else {
			count = this.length - 1;
			current = this.tail;
			while (count !== index) {
				current = current.prev;
				count--;
			}
		}
		return current;
	}
	set(index, val) {
		let foundNode = this.get(index);
		if (foundNode) {
			foundNode.val = val;
			return true;
		}
		return false;
	}
	insert(index, val) {
		if (index < 0 || index > this.length) return null;
		if (index === 0) return this.unshift(val);
		if (index === this.length) return this.push(val);

		let newNode = new Node(val);
		let beforeNode = this.get(index - 1);
		let afterNode = beforeNode.next;
		beforeNode.next = newNode;

		newNode.prev = beforeNode;
		newNode.next = afterNode;
		afterNode.prev = newNode;
		this.length++;
		return true;
	}
	remove(index) {
		if (index < 0 || index >= this.length) return false;
		if (index === 0) return this.shift();
		if (index === this.length - 1) return this.pop();

		let removeNode = this.get(index);
		let beforeNode = removeNode.prev;
		let afterNode = removeNode.next;

		beforeNode.next = afterNode;
		afterNode.prev = beforeNode;
		removeNode.next = null;
		removeNode.prev = null;
		this.length--;
		return removeNode;
	}
}

let list = new DoublyLinkedList();

list.push("HI");
list.push("THERE");
list.push("!!!");
list.push("HOW");
list.push("ARE");
list.push("YOU");
list.push("?");

- 인프런 함수형 프로그래밍 강의

ES5강의를 듣는 것도 좋지만 우선 최신 버전을 먼저 듣고, 시간이 된다면 ES5강의를 다시 들을 예정이다.
지금 강의가 할인하지 않아서 할인가 기다리면서 미리보기로 제공된 12개의 강의를 들으려 했는데 연달아서 12개 강의가 아니라 듣기가 조금 애매한 부분이 있기에 우선 이전에 사둔 함수형 코딩이라는 책을 먼저 읽고, 그 후에 강의를 듣는 것으로 목표를 변경하였다.


https://dev-minju.tistory.com/284


오후 회고 (만족도: 5)

늦은 점심과 낮은 집중도로 계획한 것들을 많이 못 했음ㅠ


- 제로베이스 REACT 강의

리스트와 key / 폼과 이벤트 제어하기


key는 왜 필요할까?

key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다.
key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야 한다.
key를 선택하는 가장 좋은 방법은 리스트의 다른 항목들 사이에서 해당 항목을 고유하게 식별할 수 있는 문자열을 사용하는 것이다. 대부분의 경우 데이터의 ID를 key로 사용한다.
렌더링 한 항목에 대한 안정적인 ID가 없다면 최후의 수단으로 항목의 인덱스를 key로 사용할 수 있다.

항목의 순서가 바뀔 수 있는 경우 key에 인덱스를 사용하는 것은 권장하지 않는다.
이로 인해 성능이 저하되거나 컴포넌트의 state와 관련된 문제가 발생할 수 있다.
https://ko.reactjs.org/docs/reconciliation.html#gatsby-focus-wrapper

Key는 배열 안에서 형제 사이에서 고유해야 하고 전체 범위에서 고유할 필요는 없다.
따라서 두 개의 다른 배열을 만들 때 동일한 key를 사용할 수 있다.


import React from "react";

class Toggle extends React.Component {
	constructor(props) {
		super(props);
		this.state = { isToggleOn: true };
	}

	handleClick() {
		this.setState((prevState) => ({
			isToggleOn: !prevState.isToggleOn,
		}));
	}

	render() {
		return (
			<button onClick={this.handleClick}>
				{this.state.isToggleOn ? "ON" : "OFF"}
			</button>
		);
	}
}

export default Toggle;

JSX 콜백 안에서 this의 의미에 대해 주의해야 한다. JavaScript에서 클래스 메서드는 기본적으로 바인딩되어 있지 않다. 
this.handleClick을 바인딩하지 않고 onClick에 전달하였다면, 함수가 실제 호출될 때 this는 undefined가 됩니다.

이는 React만의 특수한 동작이 아니며, JavaScript에서 함수가 작동하는 방식의 일부이다.

이러한 에러를 해결할 수 있는 3가지 방법

1. 바인딩
일반적으로 onClick={this.handleClick}과 같이 뒤에 ()를 사용하지 않고 메서드를 참조할 경우, 해당 메서드를 바인딩해야 한다.

this.handleClick = this.handleClick.bind(this);


2. 퍼블릭 클래스 필드 문법
클래스 필드를 사용하여 콜백을 올바르게 바인딩할 수 있습니다.

// 이 문법은 `this`가 handleClick 내에서 바인딩되도록 합니다.
// 주의: 이 문법은 *실험적인* 문법입니다.
  handleClick = () => {
    console.log('this is:', this);
  }


3. 콜백에 화살표 함수

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // 이 문법은 `this`가 handleClick 내에서 바인딩되도록 합니다.
    return (
      <button onClick={() => this.handleClick()}>
        Click me
      </button>
    );
  }
}

이 문법의 문제점은 LoggingButton이 렌더링 될 때마다 다른 콜백이 생성된다는 것이다.
대부분의 경우 문제가 되지 않으나, 콜백이 하위 컴포넌트에 props로서 전달된다면 그 컴포넌트들은 추가로 다시 렌더링을 수행할 수도 있다.
이러한 종류의 성능 문제를 피하고자, 생성자 안에서 바인딩하거나 클래스 필드 문법을 사용하는 것을 권장한다.


저녁 회고 (만족도: 7.5)

저녁에는 집중도 좋았고, 괜찮게 학습했지만 오후에 집중을 많이 못했어서 저녁에도 여파가 크다...ㅠ
그래서 오후의 영향으로 만족도 7.5점


[ 출처 : JavaScript 알고리즘 & 자료구조 마스터클래스 ]

728x90

'TDL' 카테고리의 다른 글

[TDL] 07/27 Today's-Done-List  (0) 2022.07.27
[TDL] 07/26 Today's-Done-List  (0) 2022.07.26
[TDL] 07/24 Today's-Done-List  (0) 2022.07.24
[TDL] 07/22 Today's-Done-List  (0) 2022.07.23
[TDL] 07/21 Today's-Done-List  (0) 2022.07.22