Wikipedia에 따르면 스택 :
LIFO (Last In, First Out) 추상 데이터 형식 및 선형 데이터 구조입니다.
배열 동안 :
은 적어도 하나의 배열 인덱스 또는 키로 식별되는 요소 (값 또는 변수) 모음으로 구성된 데이터 구조입니다.
내가 이해하는 한, 그들은 상당히 비슷합니다. 그렇다면 주요 차이점은 무엇입니까? 그것들이 동일하지 않다면, 스택이 할 수없는 것과 반대로 할 수있는 배열은 무엇입니까?
Wikipedia에 따르면 스택 :
LIFO (Last In, First Out) 추상 데이터 형식 및 선형 데이터 구조입니다.
배열 동안 :
은 적어도 하나의 배열 인덱스 또는 키로 식별되는 요소 (값 또는 변수) 모음으로 구성된 데이터 구조입니다.
내가 이해하는 한, 그들은 상당히 비슷합니다. 그렇다면 주요 차이점은 무엇입니까? 그것들이 동일하지 않다면, 스택이 할 수없는 것과 반대로 할 수있는 배열은 무엇입니까?
답변:
글쎄, 당신은 확실히 배열로 스택을 구현할 수 있습니다. 차이점은 액세스입니다. 배열에는 요소 목록이 있으며 언제든지 요소에 액세스 할 수 있습니다. (나무 블록을 모두 한 줄에 배치한다고 생각하십시오.)
그러나 스택에는 임의 액세스 작업이 없습니다. 스택의 맨 위에있는 요소 만 처리하는 Push
, Peek
및 만 Pop
있습니다. (수직으로 쌓인 나무 블록을 생각하십시오. 탑의 탑 아래에있는 어떤 것도 건드리지 않거나 넘어 질 것입니다.)
순수 스택에서 허용되는 유일한 작업은 Push
, Pop
및 Peek
하지만 실제적인면에서,이 정확히 사실이 아니에요. 또는 오히려 Peek
작업을 통해 스택의 임의의 위치를 볼 수 있지만 스택의 한쪽 끝을 기준으로하는 것이 좋습니다.
따라서 다른 사람들이 말했듯이 배열은 무작위 액세스이며 모든 것은 배열의 시작 부분을 참조합니다 .
스택에서는 스택의 작업 끝에서만 추가 / 제거를 수행 할 수 있지만 여전히 임의 액세스 읽기 권한이 있지만 작업 끝을 참조합니다 . 이것이 근본적인 차이점입니다.
예를 들어, 스택의 매개 변수를 함수에 전달할 때 수신자는 매개 변수를보기 위해 해당 매개 변수를 표시하지 않아도됩니다. 스택의 로컬 변수를 푸시하고 스택 포인터의 오프셋을 기반으로 모든 로컬 변수 및 매개 변수를 참조합니다. 배열 만 사용하는 경우 수신자는 해당 매개 변수를 찾을 위치를 어떻게 알 수 있습니까? 호출 수신자가 완료되면 로컬 변수를 제거하고 리턴 값을 푸시하고 제어를 호출자에게 리턴하며 호출자는 리턴 값 (있는 경우)을 팝한 다음 스택에서 매개 변수를 팝합니다. 장점은 함수 호출에 얼마나 멀리 중첩되어 있더라도 (스택 공간이 부족하지 않다고 가정) 작동한다는 것입니다.
그것은 하나의 특별한 사용 / 구현이지만 차이점을 보여줍니다 : 배열은 항상 처음부터 참조되지만 스택은 항상 일부 작업 끝 위치에서 참조됩니다.
스택의 가능한 구현 중 하나는 배열 과 작업 끝의 위치를 기억하는 인덱스입니다.
여기에서 가장 큰 혼란은 구현과 기본 데이터 구조입니다.
대부분의 (더 기본 언어) 배열은 주어진 시간에 액세스 할 수있는 고정 길이 요소 세트를 나타냅니다. 이와 같은 많은 요소가 있다는 사실은 그것이 어떻게 사용되어야하는지에 대해 아무 것도 알려주지 않습니다 (솔직히 컴퓨터는 사용법을 위반하지 않는 한 어떻게 사용하는지 알지 / 관리하지 않습니다).
스택은 특정 방식으로 처리해야하는 데이터를 나타내는 데 사용되는 추상화입니다. 이것은 상단에 추가하거나 상단에서 제거 할 수있는 일부 서브 루틴 / 메소드 / 기능이 있어야하지만 상단 아래의 데이터는 건드리지 않기 때문에 추상적 개념입니다. 이 방법으로 배열을 사용하기위한 선택입니다.
배열 (최대 크기), 동적 배열 (공간이 부족할 때 커질 수 있음) 또는 연결된 목록 등 다양한 종류의 데이터 구조에서 스택을 만들 수 있습니다. 개인적으로 링크 된 목록은 스택의 제한 사항을 가장 잘 표현한다고 생각합니다. 첫 번째 요소 이상의 것을보고 약간의 노력을 기울여야하며 앞에 추가하고 제거하기가 매우 쉽습니다.
따라서 배열을 사용하여 스택을 만들 수 있지만 동등하지는 않습니다.
나는 그들이 "매우 비슷하다"고 말하지 않을 것입니다.
배열은 나중에 순차적으로 또는 인덱스를 통해 액세스 할 항목을 보유하는 데 사용됩니다. 데이터 구조는 어떤 종류의 액세스 방법 (FIFO, LIFO, FILO 등)을 의미하지는 않지만 원하는 경우 사용할 수 있습니다.
스택은 생성되는 것들을 추적하는 방법입니다. 생성 된 스택 유형에 따라 액세스 방법이 암시 적 / 필요합니다. 프레임 스택은 LIFO 예입니다. 면책 조항-여기에 내 데이터 구조 분류 체계를 혼합하고 스택은 실제로 LIFO 만 허용 할 수 있습니다. 그렇지 않으면 다른 유형의 대기열이됩니다.
그래서 배열을 스택으로 사용할 수는 있지만 (원하지는 않지만) 스택으로 배열을 사용할 수는 없습니다 (정말 열심히 노력하지 않는 한).
배열의 데이터는 키 또는 인덱스로 액세스 할 수 있습니다. 스택의 데이터가 스택 상단에서 튀어 나오면 액세스 할 수 있습니다. 즉, 인덱스를 알고 있으면 배열에서 데이터에 쉽게 액세스 할 수 있습니다. 스택에서 데이터에 액세스한다는 것은 찾고자하는 요소를 찾을 때까지 팝업 요소를 유지해야한다는 것을 의미하므로 데이터 액세스에 시간이 오래 걸릴 수 있습니다.
배열은 프로그래머의 관점에서 제자리와 크기에 고정되어 있으며, 위치와 전체 위치를 알고 있습니다. 모든 것에 액세스 할 수 있습니다.
스택을 사용하면 스택의 한쪽 끝에 앉아 있지만 크기 나 안전하게 얼마나 멀리 갈 수 있는지 모릅니다. 그것에 대한 액세스는 할당 된 양으로 제한되며, 힙이나 프로그램 공간에 딱 들어 맞으면 원하는 양을 할당 할 때조차 알지 못하는 경우가 종종 있습니다. 스택에 대한 관점은 자신이 할당 한 작은 배열이며, 원하는 크기이며, 제어하고 볼 수 있습니다. 귀하의 부분은 배열과 다르지 않습니다. 차이점은 배열과 다른 배열의 한쪽 끝에 고정되어 논란의 여지가없고, 크기가 크거나 작다는 것을 알지 못하며, 해를 입히지 않고 만질 수 없습니다. 전역이 아닌 배열은 어쨌든 스택에 구현되는 경우가 많으므로 배열과 스택은 해당 기능 기간 동안 동일한 공간을 공유합니다.
하드웨어 측면으로 들어가고 싶다면 물론 프로세서마다 다르지만 일반적으로 배열은 알려진 시작 지점 / 주소를 기반으로하며 크기는 컴파일러 / 프로그래머가 알고 있으며 주소는 그 주소로 계산됩니다. 때때로 레지스터 오프셋 어드레싱을 사용하여 (이 기본 레지스터 값에 의해 정의 된 주소에서이 오프셋 레지스터 값을 더한 값을로드 할 때와 같이 컴파일 할 때 반드시 레지스터 기반 일 필요는 없습니다. 물론 프로세서에 따라 다름) 높은 수준의 코드로 배열에 액세스하는 것과 유사합니다. 스택과 마찬가지로, 사용 가능한 경우 레지스터 또는 즉시 오프셋 주소 지정을 사용할 수 있습니다. 종종 스택 포인터 자체 또는 스택 프레임에 액세스하기 위해 컴파일러 / 프로그래머가 예약 한 레지스터를 사용하는 특수 레지스터를 사용하지만 함수. 또한 일부 프로세서의 경우 스택에 액세스하기 위해 특수 스택 액세스 기능이 사용됩니다. 푸시 및 팝 명령이 있지만이 질문에 실제로 적용하지 않는 것처럼 자주 사용되지는 않습니다. 일부 프로세서의 경우 push 및 pop은 스택의 스택 포인터뿐만 아니라 모든 레지스터와 함께 사용할 수있는 명령어의 별칭이며이 질문과 관련하여 push 및 pop을 추가로 제거합니다.