Двухсвязный спискок. Си ++
У меня такая проблемка - я написал программу по сортировке двухсвязного списка методом выбора.
В программе я осуществляю ввод данных в список, затем его вывожу, -> затем сортирую и потом вывожу в уже отсортированном виде.
Но наткнулся на проблему- при вызове функции сортировки он зависает(я ввожу например, 3 элемента в обратном порядке 3 2 1 , затем в процессе сортировки они упорядочиваются вроде бы и становятся 1 2 3 , после чего программа виснет.)
Если же ввести 4 элемента, то при сортировки он меняет первые 3 и упорядочивает их, а 4-й почему то стоит на месте.
Если кто-то может помочь, я был бы очень признателен.
Вот код программы:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include<conio.h>
#include<iostream.h>
using namespace std;
//---------------------------------------------------------------------------
#pragma argsused
//===========================================================
class DLIST
{
public:
int value;
DLIST *beg; // = head
DLIST *end; // = end
DLIST *next;
DLIST *prev;
//=============================================================
DLIST() //конструктор
{
beg = NULL;
end = NULL;
prev = NULL;
next = NULL;
}
~DLIST()
{
DLIST *ptr, *temp;
for(ptr = beg; ; )
{
temp = ptr->next;
delete ptr;
ptr = temp;
if(ptr == end)
{
delete ptr;
break;
}
}
}
//==============================================================
void MakeDList() //описание и создание Двусвязного списка
{
DLIST *rex = new DLIST;
cin>>rex->value;
if(beg == NULL)
beg = rex;
else
{
end->next = rex;
rex->prev = end;
}
end = rex;
}// end of create function
//==============================================================
void ShowDList() //печать списка
{
bool bhead = true;
if(beg == NULL)
{
cout<<"The List is empty!"<<endl;
}
DLIST *rex = beg;
while(rex)
{
cout<<rex->value<<"\t";
rex = rex->next;
}
}//end of printing aunction
//==============================================================
void Sort()
{
DLIST *SmallElement;
DLIST *i, *j;
for(i = beg; i != NULL; i = i->next)
{
SmallElement = i;
for(j = i->next; j != NULL; j = j->next)
if(j->value < SmallElement->value)
SmallElement = j;
if(i->next != NULL) i->next->prev=SmallElement;
if(SmallElement->prev != NULL) SmallElement->prev->next=i;
if(SmallElement==end)
{
i->prev=SmallElement->prev;
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
end=SmallElement;
}
else
{
i->prev=SmallElement->prev;
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
}
if(i == end)
end = SmallElement;
if(i == beg)
beg = SmallElement;
}
} //end of Sorting function
};//end of Class
//==============================================================
int main(int argc, char* argv[])
{
DLIST *L;
L = new DLIST;
cout<<"Enter amount of elements which you want to add: ";
int SIZE;
cin>>SIZE;
int temp;
cout<<"Enter Data: "<<endl;
for(int i = 0; i < SIZE; i++)
{
L->MakeDList();
}
cout<<"\nPrinting DList:"<<endl;
L->ShowDList();
L->Sort();
cout<<"\n\nPrinting DList after sorting: "<<endl;
L->ShowDList();
getch();
return 0;
}
//---------------------------------------------------------------------------
не мог пройти мимо вашего сообщени даже на сайте зарегился :)) сам когда-то подобное писал, но в большинстве случаев я ответы находил быстрее чем отвечали форумах. Ладно к делу.
На первый взгляд видно что увас список и объекты списка описываются одним и темже классом, что ниесть гуд (за исключением случая когда вы хотите создать список списков %-) ) т.к. вы обязательно запутаетесь где вы должны работать со списком а где с элементом списка, возможно так и произошло, сейчас попробую поправить сие.
А причина ошибки толком не понятна :(
//---------------------------------------------------------------------------
//#include <vcl.h>
#pragma hdrstop
#include <conio.h>
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------
#pragma argsused
//================================================== =========
struct NODE_DLIST
{
int value;
NODE_DLIST *next;
NODE_DLIST *prev;
void _null()
{
value=0;
next=NULL;
prev=NULL;
}
};
class DLIST
{
public:
NODE_DLIST *beg; // = head
NODE_DLIST *end; // = end
//================================================== ===========
DLIST() //конструктор
{
beg = NULL;
end = NULL;
}
~DLIST()
{
NODE_DLIST *ptr, *temp;
for(ptr = beg; ; )
{
temp = ptr->next;
delete ptr;
ptr = temp;
if(ptr == end)
{
delete ptr;
break;
}
}
}
//================================================== ============
void MakeDList() //описание и создание Двусвязного списка
{
NODE_DLIST *rex = new NODE_DLIST;
rex->_null();
cin>>rex->value;
if(beg == NULL)
beg = rex;
else
{
end->next = rex;
rex->prev = end;
}
end = rex;
}// end of create function
//================================================== ============
void ShowDList() //печать списка
{
bool bhead = true;
if(beg == NULL)
{
cout<<"The List is empty!"<<endl;
}
NODE_DLIST *rex = beg;
while(rex)
{
cout<<rex->value<<"\t";
if(rex->next!=NULL)
rex = rex->next;
else break;
}
}//end of printing aunction
//================================================== ============
void Sort2()
{
if(beg==end) return; // если в списке 0 или 1 элемент то выходим
NODE_DLIST *i=beg;
while(i->next!=NULL)
{
if(i->value > i->next->value)
{
int temp=i->value;
i->value=i->next->value;
i->next->value=temp;
while(i->prev!=NULL)
{
if(i->value < i->prev->value)
{
int temp=i->value;
i->value=i->prev->value;
i->prev->value=temp;
}
i=i->prev;
}
}
i=i->next;
}
}
void Sort()
{
NODE_DLIST *SmallElement;
NODE_DLIST *i, *j;
for(i = beg; i != NULL; i = i->next)
{
SmallElement = i;
for(j = i->next; j != NULL; j = j->next)
if(j->value < SmallElement->value)
SmallElement = j;
if(i->next != NULL) i->next->prev=SmallElement;
if(SmallElement->prev != NULL) SmallElement->prev->next=i;
if(SmallElement==end)
{
i->prev=SmallElement->prev;
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
end=SmallElement;
}
else
{
i->prev=SmallElement->prev;
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
}
if(i == end)
end = SmallElement;
if(i == beg)
beg = SmallElement;
}
} //end of Sorting function
};//end of Class
//================================================== ============
int main(int argc, char* argv[])
{
DLIST *L;
L = new DLIST;
cout<<"Enter amount of elements which you want to add: ";
int SIZE;
cin>>SIZE;
int temp;
cout<<"Enter Data: "<<endl;
for(int i = 0; i < SIZE; i++)
{
L->MakeDList();
}
cout<<"Printing DList:"<<endl;
L->ShowDList();
cout<<endl<<"Sort run"<<endl;
L->Sort2();
cout<<"Sort end"<<endl;
cout<<"Printing DList after sorting: "<<endl;
L->ShowDList();
cout<<endl<<"Program end"<<endl;
getch();
return 0;
}
//---------------------------------------------------------------------------
Думаю Вам не стоит извиняться))) Тем более в этой ситуации)
Я Вам безгранично благодарен, поскольку сам вряд ли бы разобрался с этой проблемой :(
Так что Большое Вам СПАСИБО!!!
эм.. позвольте спросить в сортировке которую Вы написали, если я не ошибаюсь тут идет сравнение и обмен индексами?
Я прав?
Блин засада :(
Дело в том что в этой задаче надо было при обмене менять не индексы а связи между элементами))
Я в прошлый раз тоже так сделал, А когда начал сдавать мне преподаватель сразу дал понять, что надо делать иначе(именно после этого я и повис , когда пришлось менять связи) Бедаааа:(
//---------------------------------------------------------------------------
//#include <vcl.h>
#pragma hdrstop
#include <conio.h>
#include <iostream>
#include <stdlib.h>
#include <ctime>
using namespace std;
//---------------------------------------------------------------------------
#pragma argsused
//================================================== =========
struct NODE_DLIST
{
int value;
NODE_DLIST *next;
NODE_DLIST *prev;
void _null()
{
value=0;
next=NULL;
prev=NULL;
}
};
class DLIST
{
public:
NODE_DLIST *beg; // = head
NODE_DLIST *end; // = end
//================================================== ===========
DLIST() //конструктор
{
beg = NULL;
end = NULL;
}
~DLIST()
{
NODE_DLIST *ptr, *temp;
for(ptr = beg; ; )
{
temp = ptr->next;
delete ptr;
ptr = temp;
if(ptr == end)
{
delete ptr;
break;
}
}
}
//================================================== ============
void MakeDList(int i) //описание и создание Двусвязного списка
{
NODE_DLIST *rex = new NODE_DLIST;
rex->_null();
rex->value=i;
if(beg == NULL)
beg = rex;
else
{
end->next = rex;
rex->prev = end;
}
end = rex;
}// end of create function
//================================================== ============
void ShowDList() //печать списка
{
bool bhead = true;
if(beg == NULL)
{
cout<<"The List is empty!"<<endl;
}
NODE_DLIST *rex = beg;
while(rex)
{
cout<<rex->value<<"\t";
if(rex->next!=NULL)
rex = rex->next;
else break;
}
}//end of printing aunction
//================================================== ============
void Sort2()
{
if(beg==end) return; // если в списке 0 или 1 элемент то выходим
NODE_DLIST *i=beg;
while(i->next!=NULL)
{
if(i->value > i->next->value)
{
int temp=i->value;
i->value=i->next->value;
i->next->value=temp;
while(i->prev!=NULL)
{
if(i->value < i->prev->value)
{
int temp=i->value;
i->value=i->prev->value;
i->prev->value=temp;
}
i=i->prev;
}
}
i=i->next;
}
}
void Sort()
{
NODE_DLIST *SmallElement;
NODE_DLIST *i, *j;
for(i = beg; i != NULL; i = i->next)
{
SmallElement = i;
for(j = i->next; j != NULL; j = j->next)
if(j->value < SmallElement->value)
SmallElement = j;
if(i->next != NULL) i->next->prev=SmallElement;
if(SmallElement->prev != NULL) SmallElement->prev->next=i;
if(SmallElement==end)
{
i->prev=SmallElement->prev;
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
end=SmallElement;
}
else
{
i->prev=SmallElement->prev;
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
}
if(i == end)
end = SmallElement;
if(i == beg)
beg = SmallElement;
}
} //end of Sorting function
};//end of Class
//================================================== ============
void Test()
{
cout<<"Test run"<<endl;
const int MAX_RAND=10;//максимально возможное случайное число
const int MAX_LEN_RAND=7;//количество случайных элементов
srand(time(0));// сбрасываем генератор случайных чисел
// что бы он у нас все время герерировал разные значения
DLIST *L=new DLIST;
for(int i=0;i<MAX_LEN_RAND;i++)
{
L->MakeDList(rand() % MAX_RAND);//генерируем случайное число [0, MAX_RAND)
}
L->ShowDList();
cout<<endl;
L->Sort2();
L->ShowDList();
cout<<endl<<"Test end"<<endl<<endl;
}
int main(int argc, char* argv[])
{
for(int i=0;i<15;i++)
{
Test();
for(int j=0;j<0xfffffff;j++); //замедлялка, а то у меня на компе все
//слишком быстро и случайные значениякоторые зависят от текущего времени
//просто не успевают генерироваться
}
/*
DLIST *L;
L = new DLIST;
cout<<"Enter amount of elements which you want to add: ";
int SIZE;
cin>>SIZE;
cout<<"Enter Data: "<<endl;
for(int i = 0; i < SIZE; i++)
{
int t;
cin>>t;
L->MakeDList(t);
}
cout<<"Printing DList:"<<endl;
L->ShowDList();
cout<<endl<<"Sort run"<<endl;
L->Sort2();
cout<<"Sort end"<<endl;
cout<<"Printing DList after sorting: "<<endl;
L->ShowDList();
cout<<endl<<"Program end"<<endl;
*/
getch();
return 0;
}
//---------------------------------------------------------------------------
о_0)) Идея с тестированием - просто изумительная , никогда не задумывался о таком(а наверно стоило бы)))
Что касается самой сортировки, то тут нужен обмен вот этими адресами, в них то я видимо и накосячил. :(
добавил новые функции как говорится не нужное закоментировать
void Chahge_Node(NODE_DLIST *node1,NODE_DLIST *node2)
{
NODE_DLIST temp=*node1,node1_old=*node1,node2_old=*node2;
node1_old=node2_old;
node2_old=temp;
}
void Chahge_Value(NODE_DLIST *node1,NODE_DLIST *node2)
{
int temp=node1->value;
node1->value=node2->value;
node2->value=temp;
}
void Change_Addr(NODE_DLIST *node1,NODE_DLIST *node2)
{
if(node1==NULL || node2==NULL)return;
NODE_DLIST *node0=node1->prev,
*node3=node2->next;
node1->next=node3;
node1->prev=node2;
node2->next=node1;
node2->prev=node0;
if(node0!=NULL) node0->next=node2;
if(node3!=NULL) node3->prev=node1;
}
void Sort3()
{
if(beg==end) return; // если в списке 0 или 1 элемент то выходим
NODE_DLIST *i=beg;
while(i->next!=NULL)
{
if(i->value > i->next->value)
{
//Chahge_Node(i,i->next);
Chahge_Value(i,i->next);
//Change_Addr(i,i->next);
while(i->prev!=NULL)
{
if(i->value < i->prev->value)
{
//Chahge_Node(i,i->next);
Chahge_Value(i,i->next);
//Change_Addr(i,i->next);
}
i=i->prev;
}
}
i=i->next;
}
}
да, это изменение связей между элементами списка
с адрессами надо быть очень осторожным иначе можно не одну кружку кофе потратить на поиск ошибки которая настолько мала и ничтожна и легко исправлялась, но нервы будут уже не те, по себе знаю.
ДА вы правы-это лабораторная работа, но делая ее мы и познаем Мир)) не правда ли?)
Теперь что касается основного задания (сортировки двухсвязного списка методом выбора). Вы говорили что можете сделать сортировку методом выбора посредством обмена адресами?
Если Вас не затруднит, не могли бы Вы помочь мне с этим, поскольку я уже не знаю как ее делать(вернее я уже не в курсе что не так).
да, это изменение связей между элементами списка
с адрессами надо быть очень осторожным иначе можно не одну кружку кофе потратить на поиск ошибки которая настолько мала и ничтожна и легко исправлялась, но нервы будут уже не те, по себе знаю.
Теперь что касается основного задания (сортировки двухсвязного списка методом выбора). Вы говорили что можете сделать сортировку методом выбора посредством обмена адресами?
вы немного путаетесь в понятиях, сортировки есть медленные, быстрые и сортировка методом пузырька.
при сортировке возникает момент когда надо менять элементы списка, это можно делать изменением значений, адрессов(на которые ссылаются элементы) или заменой самих элементов. все три способа я вам написал Chahge_Node, Chahge_Value, Change_Addr.
Что касается обмена адресами, то тут я могу лишь сказать , что нас учили так, как было представлено в первоначальном моем варианте(т.е. переставлять связи на соседние элементы так, затем иначе, писать куча исключительных ситуаций, когда переставляемый элемент является первым, когда он является последним и тд). Других вариантов увы я не знаю.
{
if(node1==NULL || node2==NULL)return;
NODE_DLIST *node0=node1->prev,
*node3=node2->next;
node1->next=node3;
node1->prev=node2;
node2->next=node1;
node2->prev=node0;
if(node0!=NULL) node0->next=node2;
if(node3!=NULL) node3->prev=node1;
}
а у Вас тут достаточно интересно написано и я бы сказал просто(я о таких вариантах даже не думал)))
поверте я до этого тоже не сразу дошел, возьмите карандаш с листком и начертите начальное состаяние(до сортировки) и конечное состаяние (после сортировки) и все будет просто и легко видно, дерзайте!!
Позвольте задать вопрос: вот этот метод сортировки(который вы описали)- если я не ошибаюсь это же пузырек?
назв. до после
node1_next node3 node2
node1_prev node2 node0
node2_next node1 node1
node2_prev node0 node3
node0_next node2 node1
node3_prev node1 node2
все приходит с опытом, уверен и вы в скором времени будите блистать элегантными решениями
Позвольте задать вопрос: вот этот метод сортировки(который вы описали)- если я не ошибаюсь это же пузырек?
да похоже на то, я летом с армии пришел (из универа отчислили :( ) кучу всего забыл, вот востанавливаю по чуть-чуть, это эдакий двусторонний пузырек, большое всплывает а маленькое тонет(или наоборот) т.е. минимальное и максимально разбегаются в разные концы списка
Так , теперь осталось применить этот же метод только сортируя методом выбора(иначе не примут, поскольку в задании так и ставилось- по методу выборки)
ранее КГТУ (красноярский государственный технический университет) ныне СФУ ИКИТ(сибирский федеральный университет институт космических и информационных технологий) собственно из него и был отчислен
не понял, приведите пример и/или задание лабораторки
Отсортировать двухсвязный список по методу выборки(выбора).
При сортировке менять не значения , а связи между элементами двухсвязного списка.
//пример кода для сортировки МАССИВА методом ВЫБОРА
voidSelectSort(int A[], int n)
{
int smallIndex;
int i, j;
for(int i = 0; i < n -1; i++)
{
smallIndex = i;
for(j = i + 1; j < n; j++)
if(A[j] < A[smallIndex])
smallIndex = j;
int temp = A;
A = A[smallIndex];
A[smallIndex] = temp;
}
}
{
if(nodeA==NULL || nodeB==NULL)return;
NODE_DLIST *nodeAL=nodeA->prev,
*nodeAR=nodeA->next,
*nodeBL=nodeB->prev,
*nodeBR=nodeB->next;
nodeA->next=nodeBR;
nodeA->prev=nodeBL;
nodeB->next=nodeAR;
nodeB->prev=nodeAL;
if(nodeAL!=NULL) nodeAL->next=nodeB;
if(nodeAR!=NULL) nodeAR->prev=nodeB;
if(nodeBL!=NULL) nodeBL->next=nodeA;
if(nodeBR!=NULL) nodeBR->prev=nodeA;
}
NODE_DLIST *Find_min(NODE_DLIST *start)
{
if(beg==end || start==NULL) return beg;
NODE_DLIST *i=start,*ret_min=start;
while(i!=NULL)
{
if(i->value < ret_min->value)
{
ret_min=i;
}
i=i->next;
}
return ret_min;
}
void Sort4()//сортировка выбором
{
if(beg==end) return; // если в списке 0 или 1 элемент то выходим
NODE_DLIST *i=beg,*min_node;
while(i->next!=NULL)
{
min_node=Find_min(i);
if(min_node!=i && min_node!=NULL)
{
Change_Addr2(i,min_node);
}
i=i->next;
}
}
я вчера пытался 3-ю функцию сортировки запустить))) либо я вчера уже тупить стал, либо что-то было не так, поскольку при вызоче 2-й сортировки все было ОК.
А когда вызывал 3-ю функцию Sort3() он передавал в нее данные и повис :(
щас тоже буду пытаться шаманить :)
это как и в каком месте вы это делаете, просветите!:)
на кой черт вообще придумали эти списки? :( у меня к ним уже личная вражда начинается)))
на кой черт вообще придумали эти списки? :( у меня к ним уже личная вражда начинается)))
Элементарно все просто читаем Связные списки и задаем вопросы по своему коду, поможем
Думаю если бы все было так просто, то я бы не стал писать и просить кого-то помочь!
Что не понятно?
например то, почему это ерунда не пашет?(я конечно не исключаю возможности появления ошибок, но увы в этом и заключается сложность:( )
Поскольку с этими связями можно запросто мозг взорвать!
Пытался разгрести задачу(пока чертил на листе все связи)
код получился таким:
void Sort()
{
DLIST *SmallElement;
DLIST *i, *j;
for(i = beg; i != NULL; i = i->next)
{
SmallElement = i;
for(j = i->next; j != NULL; j = j->next)
if(j->value < SmallElement->value)
SmallElement = j;
if(i->next != NULL) i->next->prev=SmallElement;
if(SmallElement->prev != NULL) SmallElement->prev->next=i;
if(SmallElement==end)
{
i->prev=SmallElement->prev;
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
end=SmallElement;
}
else
{
i->prev=SmallElement->prev;
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
}
if(i == end)
end = SmallElement;
if(i == beg)
beg = SmallElement;
}
} //end of Sorting function
//----------------------------------
// проблема в том, что он передает в нее значения , затем начинает сортировать , и после этого виснет :(
Сортировку каким методом делали?
Сортировка методом выбора(менять не значения , а связи между элементами)
Код:
{
NODE_DLIST *SmallElement;
NODE_DLIST *i, *j;
for(i = beg; i != NULL; i = i->next)//перебираем все элементы списка(с 1-го до последнего)
{
SmallElement = i;//SmallElement - наименьший элементы списка
for(j = i->next; j != NULL; j = j->next) // j = i->next-следующий за i элемент
if(j->value < SmallElement->value)// Если j-тый элемент оказался меньше чем SmallElement
SmallElement = j; // то запоминаем его
if(i->next != NULL) i->next->prev=SmallElement;//обмен связями
if(SmallElement->prev != NULL) SmallElement->prev->next=i;
if(SmallElement==end)// Если SmallElement оказался в конце
{
i->prev=SmallElement->prev; //то меняем связи между элементами
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
end=SmallElement;
}
else // Иначе
{
i->prev=SmallElement->prev;
SmallElement->prev=i;
SmallElement->next=i->next;
i->next=SmallElement;
}
if(i == end)// Если i-ый элемент оказался последним
end = SmallElement;
if(i == beg)//Если i-тый элемент оказался первым
beg = SmallElement;
}
} //end of Sorting function
Tequilla у вас вполне возможно таже проблема, аока исправил сортировку пузырьком сейчас разберусь в сортировкой необходимой вам
з.ы. прошу извинить за "медвежью услугу"
{
if(beg==end) return; // если в списке 0 или 1 элемент то выходим
bool is_change=0;
do
{
is_change=0;
NODE_DLIST *i=beg;
while(i->next!=NULL)
{
if(i->value > i->next->value)
{
//Chahge_Node(i,i->next);
//Chahge_Value(i,i->next);
Change_Addr(i,i->next);
is_change=1;
while(i->prev!=NULL)
{
if(i->prev->value > i->value)
{
//Chahge_Node(i,i->next);
//Chahge_Value(i,i->next);
Change_Addr(i->prev,i);
is_change=1;
}
if(i->prev!=NULL)i=i->prev;
else break;
}
}
if(i->next!=NULL)i=i->next;
else break;
}
}while(is_change==1);
}
void Change_Addr(NODE_DLIST *node1,NODE_DLIST *node2)// меняем местами адресса двух рядом расположенных элементов(применимо только для Sort3())
{
if(node1==node2)return;
if(node1==NULL || node2==NULL)return;
if(node1->next==node2)
{
if(node1==beg)beg=node2;
else if(node2==beg)beg=node1;
if(node1==end)end=node2;
else if(node2==end)end=node1;
NODE_DLIST *node0=node1->prev,
*node3=node2->next;
node1->next=node3;
node1->prev=node2;
node2->next=node1;
node2->prev=node0;
if(node0!=NULL) node0->next=node2;
if(node3!=NULL) node3->prev=node1;
}
else
{
cout<<"Error! node1->next!=node2"<<endl;
}
}
//-----------------
50bites Спасибо тебе большое! за ВСЕ! особенно за уделенное время и большую дружескую помощь!)