3 분 소요

리스트는 다량의 데이터를 정리하기 위한 자료구조이다. 항목들이 차례대로 저장되어 있으며 이는 순서 또는 위치를 가진다.

추상자료형 리스트

  • n개의 element형으로 구성된 순서 있는 모임

  • 메서드는 insert(list, index, item), insert_last(list, item), insert_first(list, item), delete(list, index), get_entry(list, index), get_length(list)

  • 배열로 구성하는 경우는 구현의 난이도가 쉽다는 장점이 있지만, 크기가 고정되며 새로운 데이터를 삽입하거나 삭제할 경우 기존의 데이터를 이동해야 한다는 담점이 있음

  • 연결리스트로 구성하는 경우는 크기가 제한되지 않고 중간에 쉽게 삽입하거나 삭제할 수 있다는 장점이 있으나, 오류가 엄청나게 많이 발생함

배열로 구현한 리스트

  • 순차적인 메모리 공간을 할당하므로 리스트의 순차적 표현

  • insert(), delete()의 경우, 인덱스를 확인 후에 기존 데이터를 이동할 필요가 있음

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_SIZE 5
    
    typedef int element;
    
    typedef struct {
      int size;
      element array[MAX_SIZE];
    } ArrayList;
    
    void init_array(ArrayList *l) {
      l->size = 0;
    }
    
    int is_empty(ArrayList *l) {
      return l->size == 0;
    }
    
    int is_full(ArrayList *l) {
      return l->size == MAX_SIZE;
    }
    
    element get_entry(ArrayList *l, int idx) {
      if (idx < 0 || idx >= l->size) {
        printf("error\n");
        return 0;
      } else {
        return l->array[idx];
      }
    }
    
    void print_array(ArrayList *l) {
      for (int i = 0; i < l->size; i++) {
        printf("->%d", l->array[i]);
      }
      printf("\n");
    }
    
    void insert_last(ArrayList *l, int item) {
      if (l->size >= MAX_SIZE) {
        printf("리스트 범위 초과\n");
      } else {
        l->array[l->size++] = item;
      }
    }
    
    void insert(ArrayList *l, int index, element item) {
      if (!is_full(l) && (index >= 0) && (index <= l->size)) {
        for (int i = (l->size - 1); i >= index; i--) {
          l->array[i + 1] = l->array[i];
        }
        l->array[index] = item;
        l->size++;
      }
    }
    
    void clear(ArrayList *l){
      for (int i = l->size; i>-1; i--){
        l->array[i] = 0;
      }
      l->size = 0;
    }
    
    void replace(ArrayList *l, int index, int item){
      if (index < 0 || index > l->size){
        printf("유효 인덱스가 아닙니다.\n");
      } else{
        l->array[index] = item;
      }
    }
    
    element delete (ArrayList *l, int index) {
      if (index < 0 || index >= l->size) {
        printf("유효한 인덱스 아닙니다.\n");
        return 0;
      } else {
        element item;
        item = l->array[index];
        for (int i = index; i < l->size - 1; i++) {
          l->array[i] = l->array[i + 1];
        }
        l->size--;
        return item;
      }
    }
    
    int get_length(ArrayList *l){
      return l->size;
    }
    
    int main(void) {
      ArrayList list;
      init_array(&list);
      insert(&list, 0, 10);
      print_array(&list);
      insert(&list, 0, 20);
      print_array(&list);
      insert(&list, 0, 30);
      print_array(&list);
      insert(&list, 0, 40);
      print_array(&list);
      insert_last(&list, 70);
      print_array(&list);
      delete(&list, 0);
      print_array(&list);
      printf("%d\n", get_length(&list));
      replace(&list, 4, 90);
      print_array(&list);
      replace(&list, 0, 50);
      print_array(&list);
    
      delete(&list, 2);
      print_array(&list);
    
    
      return 0;
    }
    
    

연결 리스트

  • 동적으로 크기가 변할 수 있으며, 삭제나 삽입 시에 데이터를 이동할 필요가 없는 리스트

  • 노드는 데이터 필드링크 필드로 나뉘어짐

  • 데이터 필드는 저장해야 하는 데이터, 링크 필드는 다른 노드를 가리키는 포인터가 저장

  • 이때 링크 필드는 자기 자신을 참조하는 포인터를 포함하는 구조체인 자기참조구조체의 형태로 관리

  • 연결 리스트마다 첫 번째 노드를 가리키고 있는 변수 - 헤드 포인터

  • 마지막 노드의 링크 필드는 연결된 것이 없으므로 NULL로 설정

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct ListNode{
      int data;
      struct ListNode *link;
    } ListNode;
    
    ListNode* insert_first(ListNode *head, int item){
      ListNode *p = (ListNode *)malloc(sizeof(ListNode));
      p->data=item;
      p->link=head;
      head = p;
      return head;
    }
    
    ListNode* insert(ListNode *head, ListNode *pre, int value){
      ListNode *p = (ListNode *)malloc(sizeof(ListNode));
      p->data = value;
      p->link = pre->link;
      pre->link = p;
      return head;
    }
    
    ListNode* delete_first(ListNode *head){
      ListNode *removed;
      if (head == NULL) return NULL;
      removed = head;
      head = removed->link;
      free(removed);
      return head;
    }
    
    ListNode* delete(ListNode *head, ListNode *pre){
      ListNode *removed;
      removed = pre->link;
      pre->link = removed->link;
      free(removed);
      return head;
    }
    
    void print_list(ListNode *head){
      for (ListNode *p = head; p!=NULL; p = p->link){
        printf("%d->", p->data);
      }
      printf("NULL \n");
    }
    
    int get_entry(ListNode *head, int index){
      if (index < 0)
        return -1;
      ListNode *tmp;
      tmp = head;
      for (int i = 0; i < index && tmp != NULL; i++){
        tmp = tmp->link;
      }
      return tmp->data;
    }
    
    int get_length(ListNode *head){
      ListNode *tmp;
      int length = 0;
      tmp = head;
      if (head == NULL){
        return length;
      }
    
      for (int i = 0;  tmp != NULL; i++){
        length += 1;
        tmp = tmp->link;
    
      }
      return length;
    }
    
    int find_value(ListNode *head, int value){
      ListNode *tmp = head;
      for (int i = 0; tmp != NULL; i++){
        if (tmp -> data == value){
          return i;
        }
        tmp = tmp -> link;
    
      }
      return -1;
    }
    
    ListNode* reverse(ListNode *head){
      ListNode *p, *q, *r;
      p = head;
      q = NULL;
      while (p!=NULL){
        r = q;
        q = p;
        p = p->link;
        q -> link= r;
      }
      return q;
    }
    
    int main(){
      ListNode *head = NULL;
    
      for (int i=0 ; i<10; i++){
        head = insert_first(head, i);
        print_list(head);
      }
      printf("%d\n", find_value(head, 8));
      printf("%d\n", get_entry(head, 0));
      printf("%d\n", get_length(head));
      printf("%d\n", get_entry(head, 9));
    
      head = reverse(head);
      print_list(head);
      for (int i = 0; i<10; i++){
        head = delete_first(head);
        print_list(head);
      }
    }
    

댓글남기기