HOME    FORUMS    MEMBERS    RECENT POSTS    LOG IN  
Баннер 1   Баннер 2

ANTICHAT — форум по информационной безопасности, OSINT и технологиям

ANTICHAT — русскоязычное сообщество по безопасности, OSINT и программированию. Форум ранее работал на доменах antichat.ru, antichat.com и antichat.club, и теперь снова доступен на новом адресе — forum.antichat.xyz.
Форум восстановлен и продолжает развитие: доступны архивные темы, добавляются новые обсуждения и материалы.
⚠️ Старые аккаунты восстановить невозможно — необходимо зарегистрироваться заново.
Вернуться   Форум АНТИЧАТ > ПРОГРАММИРОВАНИЕ > С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #3331  
Старый 25.07.2009, 15:46
horlyk
Участник форума
Регистрация: 02.12.2007
Сообщений: 132
Провел на форуме:
233095

Репутация: 21
Отправить сообщение для horlyk с помощью ICQ
По умолчанию

Я понимаю листы так:

Он состоит из головы, узла с данными и хвоста. Но я не могу понять роли каждого из элементов. Ну на пример, я вижу роли так - в узле содержатся данные и адрес следующего узла. В голове содержится адрес первого узла. В хвосте содержится адрес головы или как?

В общем посидел, подумал поэкспериментировал...

Код:
#include <iostream>
using namespace std;

class List
{
	public:
		List* next;		
		int data;
};

class Head
{
	public:
		List* next;
};

/*class Tail
{
	public:
		List* last;
};*/


void main()
{
// начало списка, создание первого узла и головы
	List* Node = new List;
	Head* head = new Head;
	//Tail* tail = new Tail;
	head->next = Node;
	int i = 1;
//Добавление:
	while(1)
	{
		cout << "data #" << i << " = ";
		cin >> Node->data;		
		i++;
			if(!Node->data)
			{		
				//tail->last = Node;
				break;
			}
		
		Node->next = new List;
		Node = Node->next;
	
	}

	cout << head->next->data << endl;
}

1. Правильный ли я лист создал?
2. Как мне вывести все значения в листе, начиная с головы?(данный вариант вывода показывает только одно значение с первого узла, хотя в отладке я вижу полную иерархию всех значений)
3. Если лист правильный, то можно ли его оптимизировать?
4. Что вообще нужно с хвостом делать?

Последний раз редактировалось horlyk; 25.07.2009 в 16:50..
 
Ответить с цитированием

  #3332  
Старый 25.07.2009, 18:32
FireFenix
Постоянный
Регистрация: 03.06.2009
Сообщений: 385
Провел на форуме:
3178262

Репутация: 389
По умолчанию

Смысл в том, ч то у нас есть элемент, в котором
Код:
Односвязный список
info - тело несущее информацию
after - адрес следующего элемента
Код:
Двусвязный список
befor - адрес предидущего элемента
info - тело несущее информацию
after - адрес следующего элемента
тогда зная адрес первого элемента - можно обрататиться к цепочки. Когда after = NULL - значит конец цепочки
Чтобы получить нужный элемент, мы начиная с первого в цикле прыгаем на адрес следуеющего элемента => количество прыжков = индекс эелмента

Пример на C - работа с односвязным списком:
Код:
#include <iostream>
#include <cstdlib>

#define length 20

void create(char filename[]);
void open(char filename[], struct s_item *item[]);
int find(struct s_item *item[]);

int add_item(struct s_item item, int position);
int del_item(int position);
int erase_item();
int show_items();

struct s_item
{
    int id;
    char name[length];
};

struct p_item
{
    struct s_item info;
    struct p_item *next;
};

struct p_item *first;
struct p_item *counter;

int main()
{
    system("chcp 1251");
    printf("\n");
    
    struct s_item item;

    char menu;
    char filename[length];
    int high;
    int size;
    int position;
    
    first = NULL;
    
    while(true)
    {
        printf("Введите номер действия :\n");
        printf("========================\n");
        printf("1 - Добавить\n");
        printf("2 - Вставить\n");
        printf("3 - Удалить\n");
        printf("4 - Очистить\n");
        printf("5 - Вывести\n");
        printf("6 - Выход\n\n");
        
        printf("Номер = "); scanf("%i", &menu);
        printf("\n");

        if (menu == 1 || menu == 2)
        {
            printf("Введите номер товара : ");        scanf("%i", &item.id);
            printf("Введите наименование товара : "); scanf("%s", &item.name);
            printf("\n");
        }


        switch(menu)
        {
            case 1:
                position = -1;
                add_item(item, position);
            break;

            case 2:
                printf("Введите позицию вставки : "); scanf("%i", &position);
                printf("\n");
                add_item(item, position);
            break;

            case 3:
                printf("Введите позицию удаления : "); scanf("%i", &position);
                printf("\n");
                del_item(position);
            break;

            case 4:
                erase_item();
            break;

            case 5:
                show_items();
            break;

            case 6:
                return EXIT_SUCCESS;
            break;

            default:
                return EXIT_SUCCESS;
            break;
        }
    }

    return EXIT_SUCCESS;
}

int erase_item()
{
    struct p_item *now;
    
    counter = first;
    
    while (counter != NULL)
    {
         now = counter->next;
         counter->next = NULL;
         
         free(counter);
         
         counter = now;
    }
    
    first = NULL;
}
  
int add_item(struct s_item item, int position)
{
    struct p_item *now;  
    struct p_item *tmp;
    
    now = (p_item *) malloc(sizeof(p_item));
    
    if (now == NULL)
    {
        printf("Not enough memory to allocate buffer\nProgramm halted...\n");
    } else {                       
        now->info = item;
        now->next = NULL;
        
        if (first == NULL)
        {
            first = now;
        } else {    
            switch (position)
            {
                case -1:
                    counter = first;

                    while (counter->next != NULL)
                    {
                        counter = counter->next;
                    }

                    counter->next = now;
                break;
                    
                case 0:
                    tmp = first;
                    first = now;
                    now = tmp;
                    first->next = now;
                    
                    printf("%i - %i = %i", first->next, now, now->next);

                break;

                default:
                    counter = first;

                    for (int i = 2; i <= position; i++)
                    {
                        counter = counter->next;

                        if (counter == NULL)
                        {
                            printf("Position not in array!\n");
                            return 0;
                        }
                    }

                    now->next = counter->next;
                    counter->next = now;
                break;
            }
            
            return 1;
        }
    }
    
    return 0;
}

int del_item(int position)
{
    struct p_item *now;

    if (first == NULL)
    {
        return 0;
    } else {    
        if (position > -1)
        {
            if (position == 0)
            {
                now = first;
                first = first->next;              
            } else {
                counter = first;
                now = counter->next;
    
                for (int i = 2; i <= position; i++)
                {
                    counter = counter->next;
                    now = counter->next;
                    
                    if (now == NULL)
                    {
                        printf("Position not in array!\n");
                        return 0;
                    }
                }
                
                counter->next = now->next;
                now->next = NULL;
            }
            
            free(now);
        } else {            
            counter = first;
            now = counter->next;
            
            while (now->next != NULL)
            {
                counter = counter->next;
                now = counter->next;
            }
            
            free(now);
            counter->next = NULL;
        }
        
        return 1;
    }
    
    return 0;
}

int show_items()
{
    counter = first;
    
    if (first == NULL)
    {
        printf("Записей нет!\n\n");
    } else {
        printf("Вывод товара\n");
        printf("=============\n");

        while(counter != NULL)
        {
            printf("Номер товара = %i\n", counter->info.id);
            printf("Наименование товара = %s\n",  counter->info.name);
            printf("\n");
            
            counter = counter->next;
        }
        
        printf("\n");
    }
}

Последний раз редактировалось FireFenix; 25.07.2009 в 18:54..
 
Ответить с цитированием

  #3333  
Старый 25.07.2009, 19:16
horlyk
Участник форума
Регистрация: 02.12.2007
Сообщений: 132
Провел на форуме:
233095

Репутация: 21
Отправить сообщение для horlyk с помощью ICQ
По умолчанию

FireFenix, спасибо, но мне пока сложно большие примеры разбирать. В книге тоже не маленький, потому и много сложностей.

Если не сложно - разберите прогу что я написал с ответами на вопросы тобишь доработкой.

Спасибо.
 
Ответить с цитированием

  #3334  
Старый 25.07.2009, 20:19
Ra$cal
Постоянный
Регистрация: 16.08.2006
Сообщений: 640
Провел на форуме:
1354067

Репутация: 599


По умолчанию

ты представь состав из вагонов. как понять, что вагон начинает состав? у него нет предыдущего вагона.
как понять, что вагон последний - у него нет следующего.
так и со списками. голова и хвост - это логические описание конкретного элемента списка. это не отдельный тип элемента списка. в этом собсно суть.
в твоем примере нужен только класс лист. переименуй его в ListItem. он сожержит данные и указатель на следующий элемент.
Добавь еще один класс - List. он как раз управляет элементами и содержит поле ListItem* head;
Если кратко получишь такое

Код:
class ListItem{
public:
    ListItem(int _data){
        data = _data;
        next = 0;
    };
    int data;
    ListItem* next;
};

class List{
public:
    void add(int data){
		getTail()->next = new ListItem(data);
		};
		
        
    bool find(int data);
    bool del(int data);
private:
	ListItem* getTail(){
		ListItem* item = head;
		while(item->next){
			item = item->next;
		}
		return item;
	};
	
    ListItem* head;
};

Последний раз редактировалось Ra$cal; 25.07.2009 в 21:15..
 
Ответить с цитированием

  #3335  
Старый 25.07.2009, 21:40
horlyk
Участник форума
Регистрация: 02.12.2007
Сообщений: 132
Провел на форуме:
233095

Репутация: 21
Отправить сообщение для horlyk с помощью ICQ
По умолчанию

Ra$cal, спасибо, буду разбираться.
 
Ответить с цитированием

  #3336  
Старый 26.07.2009, 16:21
horlyk
Участник форума
Регистрация: 02.12.2007
Сообщений: 132
Провел на форуме:
233095

Репутация: 21
Отправить сообщение для horlyk с помощью ICQ
По умолчанию

и кстати, нашел интересную инфу о листах, главное очень понятно и толково рассказано.

линк

Там в нескольких шагах рассказано все.

З.Ы. Что значит к примеру такое объявление, выделенное красным цветом, тоесть две звездочки и для чего оно нужно?:

void POSTROENIE (node **phead)

Последний раз редактировалось horlyk; 26.07.2009 в 16:26..
 
Ответить с цитированием

  #3337  
Старый 26.07.2009, 17:08
razb
Постоянный
Регистрация: 24.03.2009
Сообщений: 670
Провел на форуме:
2868783

Репутация: 414


Отправить сообщение для razb с помощью ICQ
По умолчанию

Цитата:
void POSTROENIE (node **phead)
косвенная адресация (указатель на указатель), можно использовать для работы с массивами.
 
Ответить с цитированием

  #3338  
Старый 26.07.2009, 18:26
horlyk
Участник форума
Регистрация: 02.12.2007
Сообщений: 132
Провел на форуме:
233095

Репутация: 21
Отправить сообщение для horlyk с помощью ICQ
По умолчанию

А преимущество в чем?
 
Ответить с цитированием

  #3339  
Старый 26.07.2009, 18:54
Ra$cal
Постоянный
Регистрация: 16.08.2006
Сообщений: 640
Провел на форуме:
1354067

Репутация: 599


По умолчанию

только так можно сделать многомерные массивы аля матрица

на счет описания. сложно оценить. в списке я не вижу никаких трудностей. то что ты стал мутить с классами - проблема не в списке. проблема в использовании ООП. ты создал отдельные классы для сущностей, которые не отличаются ничем в поведении. все равно что создавать класс для числа 1, другой класс для числа 2, итд. Так что стоит внимательнее перечитать, что пишут про выделение классов. Все таки их разделяют не именам, а по поведению. Если поведение не отличается - делается переменная этого класса, имеющая имя, которое характеризует назначение этого объекта. вот если бы хвост например не мог содержать число 555, а голова число 777, то тут есть повод выделить доп классы, потому как поля вроде как одинаковые, но поведение отличается.

ps: стиль именования в статье ужасен просто аж ппц. и постоянные размыеновавния. как будто человек не знает про "->"

Последний раз редактировалось Ra$cal; 26.07.2009 в 19:04..
 
Ответить с цитированием

  #3340  
Старый 26.07.2009, 20:21
horlyk
Участник форума
Регистрация: 02.12.2007
Сообщений: 132
Провел на форуме:
233095

Репутация: 21
Отправить сообщение для horlyk с помощью ICQ
По умолчанию

Цитата:
Сообщение от Ra$cal  
только так можно сделать многомерные массивы аля матрица

на счет описания. сложно оценить. в списке я не вижу никаких трудностей. то что ты стал мутить с классами - проблема не в списке. проблема в использовании ООП. ты создал отдельные классы для сущностей, которые не отличаются ничем в поведении. все равно что создавать класс для числа 1, другой класс для числа 2, итд. Так что стоит внимательнее перечитать, что пишут про выделение классов. Все таки их разделяют не именам, а по поведению. Если поведение не отличается - делается переменная этого класса, имеющая имя, которое характеризует назначение этого объекта. вот если бы хвост например не мог содержать число 555, а голова число 777, то тут есть повод выделить доп классы, потому как поля вроде как одинаковые, но поведение отличается.

ps: стиль именования в статье ужасен просто аж ппц. и постоянные размыеновавния. как будто человек не знает про "->"
Ну про код - согласен, но картинки сделали более понятным представление головы и дальнейшее построение списка.

З.Ы. Сейчас пишу прогу по созданию листа. Уже реализовал заполнение листа данными, вывод данных на экран, поиск во всем листе и вывод найденных данных на экран и удаление всего листа. Теперь хочу реализовать добавление в средину (или куда-то еще, то есть сдвиг) узла в лист и удаление одного узла.

З.Ы.Ы Можно плз примерчик многомерными массивами(с использованием **указателя)

З.Ы.Ы.Ы Еще раз спасибо за объяснения
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Часто задаваемые вопросы по MySQL Серый PHP 5 28.12.2006 18:26
Интернетчики задали российскому президенту очень странные вопросы podkashey Мировые новости. Обсуждения. 4 07.07.2006 16:53
Вопросы по Ipb 2.0 Voodoo_People Уязвимости CMS / форумов 26 15.02.2005 22:57



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ