Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Отчёт_Списки.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
262.9 Кб
Скачать

InsertOrder Упорядоченный список

template <class T>

void InsertOrder(Node<T>* & head, T item)

{

// currPtr пробегает по списку

Node<T> *currPtr, *prevPtr, *newNode;

// prevPtr == 0 указывает на совпадение в начале списка

prevPtr = 0;

currPtr = head;

// цикл по списку и поиск точки вставки

while (currPtr != 0)

{

// точка вставки найдена, если item < текущего data

if (item < currPtr->data)

break;

prevPtr = currPtr;

currPtr = currPtr->NextNode();

}

// вставка

if (prevPtr == 0)

// если prevPtr == 0, вставлять в начало

InsertFront(head,item) ;

else

{

// вставить новый узел после предыдущего

newNode = GetNode(item);

prevPtr->InsertAfter (newNode) ;

}

}

// удаление свех узлов в связанном списке

template <class T>

void ClearList(Node<T> * &head)

{

Node<T> *currPtr, *nextPtr;

currPtr = head;

while(currPtr != 0)

{

// записать адрес следующего узла, удалить текущий узел

nextPtr = currPtr->NextNode();

delete currPtr;

currPtr = nextPtr;

}

// пометить как пустой

head = 0;

}

LinkSort

template <class T>

void LinkSort(T a[], int n)

{

Node<T> *ordlist = 0, *currPtr;

int i;

// вставлять элементы из массива в список с упорядочением

for (i=0;i < n;i++)

InsertOrder(ordlist, a[i]);

// сканировать список и копировать данные в массив

currPtr = ordlist;

i = 0;

while(currPtr != 0)

{

a[i++] = currPtr->data;

currPtr = currPtr->NextNode();

}

// удалить все узлы, созданные в упорядоченном списке

ClearList(ordlist);

}

Сортировка вставками

#include <iostream>

#include "node.h"

#include "nodelib.h"

using namespace std;

// сканировать массив и печатать его элементы

void PrintArray(int a[], int n)

{

for(int i=0;i < n;i++)

cout << a[i] << " ";

}

int main()

{

system("chcp 650

01");

// инициализировать массив с 10 целыми значениями

int A[10] = {82,65,74,95,60,28,5,3,33,55};

LinkSort(A,10); // сортировать массив

cout << " Отсортированный массив: ";

PrintArray(A,10); // печать массива

cout << endl;

}

Результат:

Отсортированный массив: 3 5 28 33 55 60 65 74 82 95

Двусвязный циклический список

В случаях, когда нам необходимо обращаться к узлам в любом направлении, полезным является двусвязный список (doubly linked list). Узел в двусвязном списке содержит два указателя для создания мощной и гибкой структуры обработки списков.

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

В двусвязном списке узел может удалить сам себя из списка, изменяя два указателя.

Листинг 12: Двусвязный список

#pragma once

template <class T>

class DNode

{

private:

// циклические связи влево и вправо

DNode<T> *left;

DNode<T> *right;

public:

// данные открытые

T data;

// конструкторы

DNode(){}

DNode (const T& item);

// методы модификации списка

void InsertRight(DNode<T> *p);

void InsertLeft(DNode<T> *p);

DNode<T> *DeleteNode(void);

// получение адреса следующего (вправо и влево) узла

DNode<T> *NextNodeRight(void) const { return right; }

DNode<T> *NextNodeLeft(void) const { return left; }

};

template<class T>

DNode<T>::DNode(const T& item)

{

// установить узел для указания на самого себя и

// инициализировать данные

left = right = this;

data = item;

}

// вставить узел р справа от текущего

template <class T>

void DNode<T>::InsertRight(DNode<T> *p)

{

// связать р с его предшественником справа

p->right = right;

right->left = p;

// связать р с текущим узлом

p->left = this;

right = p;

}

// вставить узел р слева от текущего

template <class T>

void DNode<T>::InsertLeft(DNode<T> *p)

{

// связать р с его предшественником слева

p->left = left;

left->right = p;

// связать р с текущим узлом

p->right = this;

left = p;

}

// отсоединить текущий элемент от списка и возвратить его адрес

template <class T>

DNode<T> *DNode<T>::DeleteNode(void)

{

left->right = right;

right->left = left;

return this;

}

Проверка:

#include <iostream>

#include "dnode.h"

using namespace std;

int main()

{

DNode<int> node(3);

DNode<int> *p = new DNode<int>(1), *f;

node.InsertLeft(p);

p = new DNode<int>(2);

node.InsertLeft(p);

p = new DNode<int>(5);

node.InsertRight(p);

p = new DNode<int>(4);

node.InsertRight(p);

f = node.NextNodeLeft()->NextNodeLeft();

p = f;

do{

cout << p->data << endl;

p = p->NextNodeRight();

}while(p!=f);

}