Обмен технологиями

07.24.11Структура данных (6.1215) реализация стека реализации двусвязного списка

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Так же, как и при написании функциональных интерфейсов для односвязных списков, давайте сначала напишем несколько интерфейсов для двусвязных списков, чтобы ознакомиться с их основной структурой:

#включать<stdio.h>
#включать<stdlib.h>

typedef int LDataType;

//Узел двустороннего циклического связанного списка
typedef struct ListNode{
LDataType _data;
//Указываем на начальную позицию следующего узла
структура ListNode* _next;
//Указываем на начальную позицию предыдущего узла
структура LIst* _prev;
}УзелСписка;

//Двусторонний кольцевой связанный список
typedef struct Список{
структура ListNode* _head;
}Список;

структура ListNode* createListNode(LDataType val){
структура ListNode* узел = (структура ListNode*)malloc(sizeof(структура ListNode));
узел-&gt;_данные = значение;
узел-&gt;_следующий = NULL;
узел-&gt;_prev = NULL;
}

void ListInit(Список* lst){
//Пустой связанный список
lst-&gt;_head = createListNode(0);
lst-&gt;_head-&gt;_next = lst-&gt;_head-&gt;_prev = lst-&gt;_head;

}
//Вставка хвоста O(1) //Вставка данных перед заголовком ListInsert(lst, lst-&gt;_head, val);
void ListpushBack(List* lst, LDataType val){
если (lst == NULL){
возвращаться;
структура ListNode* last = lst-&gt;_head-&gt;_prev;
структура ListNode* newNode = createListNode(val);
//_head ... последний новый узел
последний-&gt;_следующий = новыйУзел;
newNode-&gt;_prev = последний;

newNode-&gt;_next = lst-&gt;_head;
lst-&gt;_head-&gt;_prev = новыйУзел;
    }
}

//Удалить хвост://Удалить предыдущий узел головы ListErase(lst, lst-&gt;_head-&gt;_prev);
void ListPopBack(Список* lst){
если (lst == NULL)
возвращаться;
//Определяем, пуст ли связанный список
если (lst-&gt;_head-&gt;_next == lst-&gt;_head)
возвращаться;
структура ListNode* last = lst-&gt;_head-&gt;_prev;
структура ListNode* prev = last-&gt;_prev;

свободный(последний);

lst-&gt;_head-&gt;_prev = предыдущая;
предыдущая-&gt;_следующая = последняя-&gt;_головная;
}

void printList(Список* lst){
структура ListNode* cur = lst-&gt;_head-&gt;_next;
в то время как (cur != lst-&gt;_head){
printf("%d", cur-&gt;_data);
текущ = текущ-&gt;_следующий;
    }
printf("н");
}

//Вставка головы//ListInsert(lst,lst-&gt;_head-&gt;_next,val);
void ListPushFront(List* lst, LDataType val){
если (lst == NULL)
возвращаться;
структура ListNode* next = lst-&gt;_head-&gt;_next;
структура ListNode* newNode = createListNode(val);

//_head, новыйУзел, следующий
lst-&gt;_head-&gt;_next = новыйУзел;
newNode-&gt;_prev = lst-&gt;_head;

newNode-&gt;_next = следующий;
следующий-&gt;_предыдущий = новыйУзел;
}

//Удалить заголовок//ListErase(lst,lst-&gt;_head-&gt;_next);
void ListPopFront(Список* lst){
если (lst == NULL || lst-&gt;_head == lst-&gt;_head)
возвращаться;
структура ListNode* next = lst-&gt;_head-&gt;_next;
структура ListNode* nextnext = next-&gt;_next;
    
следующий-&gt;_предыдущий = следующий-&gt;_следующий;
lst-&gt;_head-&gt;_next = nextnext;

бесплатно(следующий);
    
}

void ListErase(List* lst, struct ListNode* node){
//Невозможно удалить головной узел
если (lst == NULL || lst-&gt;_head == узел)
возвращаться;
//предыдущий, узел, следующий
структура ListNode* prev = node-&gt;_prev;
структура ListNode* следующий = узел-&gt;_следующий;

предыдущий-&gt;_следующий = следующий;
следующий-&gt;_предыдущий = предыдущий;

свободный(узел);

}

void ListInsert(List* lst, struct ListNode* node, LDataType val){
если (lst == NULL)
возвращаться;
структура ListNode* prev = node-&gt;_prev;
структура ListNode* newNode = createListNode(val);

//предыдущий узел newNode
предыдущий-&gt;_следующий = новыйУзел;
newNode-&gt;_prev = предыдущий;

новыйУзел-&gt;_следующий = узел;
узел-&gt;_предыдущий = новыйУзел;
}

//разрушать
СписокDestoty(Список* lst){
если (lst){
если (lst-&gt;_head){
структура ListNode* cur = lst-&gt;_head-&gt;_next;
в то время как (cur != lst-&gt;_head){
структура ListNode* next = cut-&gt;_next;
бесплатно(тек);
текущий = следующий;
            }

бесплатно(lst-&gt;_head);
        }
    }
}

недействительный тест(){
Список lst;
ListInit(&lst);
ListPushFront(&lst, 5);
printList(&lst);
ListPushFront(&lst, 1);
printList(&lst);
ListPushFront(&lst, 2);
printList(&lst);
ListPushFront(&lst, 3);
printList(&lst);
ListPushFront(&lst, 4);
printList(&lst);
ListPopFront(&lst);
printList(&lst);
ListPopFront(&lst);
printList(&lst);
ListPopFront(&lst);
printList(&lst);

/*ListPopBack(&lst);
printList(&lst);
ListPopBack(&lst);
printList(&lst);
ListPopBack(&lst);
printList(&lst);
ListPopBack(&lst);
printList(&lst);*/
}

инт основной(){

тест();
система("пауза");
вернуть 0;
}

Разница и связь между списком последовательностей и связанным списком:

Преимущества и недостатки таблицы последовательностей: Отлично: пространство является непрерывным, поддерживает произвольный доступ, имеет высокую степень использования пространства и вряд ли приведет к фрагментации памяти, а также имеет высокую эффективность вставки и удаления хвостов.

Недостатки: 1. Временная сложность вставки и удаления средней или передней части составляет O(N) 2. Стоимость расширения емкости относительно высока: подать заявку на выпуск копии

Преимущества и недостатки связанных списков (двусторонние случайные связанные списки)

Преимущества: 1. Временная сложность вставки и удаления в любой позиции составляет O(1) 2. Нет проблемы расширения емкости, вставка открывает пространство, а эффективность вставки и удаления в любой позиции высока.

Недостатки: он хранится в узлах, не поддерживает произвольный доступ, а низкое использование пространства может легко вызвать фрагментацию памяти.

стопки и очереди

Стек: специальный линейный список, который позволяет вставлять и удалять элементы только на одном конце. Конец, где выполняются операции вставки и удаления данных, называется вершиной стека, а другой конец — нижней частью стека. в стеке следует принципу LIFO (последним пришел — первым ушел)

Перемещение стека: операция вставки в стек называется push/push/push, и вставленные данные находятся на вершине стека.

Удаление: операция удаления стека называется извлечением, и данные извлечения также находятся на вершине стека.

Реализация операции push ---&gt;сохранение элементов с вершины стека

Таблица последовательности: ее можно рассматривать как операцию вставки хвоста.

Связанный список: (круговой связанный список с двусторонним заголовком). Глава списка считается вершиной стека, которая является вставкой головы, а хвост списка считается вершиной стека, который является вставка хвоста

Операция Pop pop ---&gt; удалить элементы с вершины стека

Таблица последовательности: конец таблицы считается вершиной стека и считается операцией удаления хвоста.

Связанный список: (круглый связанный список с двусторонним заголовком). Глава списка считается вершиной стека, что является удалением головы, а хвост списка считается вершиной стека, который является вершиной стека. удаление хвоста.

#включать<stdio.h>
#включать<stdlib.h>

typedef int STDataType;
//Таблица последовательности реализует стек
typedef структура стека{
STDataType* _data;
int _size;
int _capacity;
}куча;

void stackInit(стек* ст){
если (ст == NULL)
возвращаться;
st-&gt;_data = NULL;
st-&gt;_size = st-&gt;_capacity = 0;
}

void checkCapcacity(стек* st){
если (st-&gt;_size == st-&gt;_capacity){
int newCapcacity = st-&gt;_capacity == 0 ? 1 : 2 * st-&gt;_capacity;
st-&gt;_data = (STDataType*)realloc(st-&gt;_data, sizeof(STDataType)* newCapcacity);
st-&gt;_capacity = newCapcacity;
    }

}

//Помещаем в стек
void stackPush(стек* st, STDataType val){
если (ст == NULL)
возвращаться;
checkCapacity(ст);
//Вставка хвоста
st-&gt;_data[st-&gt;_size++] = значение;

}

//поп
void stackPop(стек* ст){
если (ст == NULL)
возвращаться;
если (ст-&gt;_размер &gt; 0)
ст-&gt;_размер--;
}

STDataType stackTop(стек* st){
вернуть st-&gt;_data[st-&gt;_size - 1];
}

int stackSize(стек* ст){
если (ст == NULL)
вернуть 0;
вернуть st-&gt;_size;
}

недействительный тест(){
стек ул;
stackInit(&st);
stackPush(&st, 1);
stackPush(&st, 2);
stackPush(&st, 3);
stackPush(&st, 4);
для (int i = 0; i &lt; 4; ++i){
printg("%d", stackTop(&st));
stackPop(&st);
    }
printf("н");
}

инт основной(){
тест();
система("пауза");
вернуть 0;
}