liste circulaire, ca marche mais j ai quelque questions.

liste circulaire, ca marche mais j ai quelque questions. - Algo - Programmation

Marsh Posté le 06-03-2004 à 08:14:05    

circle.h qui nous as etait donne.

Code :
  1. **********************************************************
  2.        ADT circle of Item
  3.        A circle of Item is maintained in a clockwise direction.
  4.        There is no beginning or end but the current position
  5.        is maintained for a non-empty circle.
  6. ************************************************************/
  7. #ifndef CIRCLE_H
  8. #define CIRCLE_H
  9. typedef int Item;
  10. class circle{
  11.   public:
  12.     circle();             // Pre  : none
  13.                           // Post : an empty circle is created
  14.     circle(const circle & c);   // copy constructor
  15.     ~circle();            // destructor  
  16.                           // deletes all Items in circle
  17.     void insert(Item x);  // Pre  : none
  18.                           // Post : x is inserted before (clockwise)
  19.                           //        the current position (if one exists);
  20.                           //        the new current position is the new Item
  21.     void remove();        // Pre  : the circle is not empty
  22.                           // Post : the current Item is removed from  
  23.                           //        the circle;  
  24.                           //        the new current position is the Item
  25.                           //        after (clockwise) the deleted Item*/
  26.     void move(int k);     // Pre  : the circle is not empty
  27.                           // Post : have moved the current position
  28.                           //        k places (clockwise) around the circle */
  29.     Item getCurrent();    // Pre  : the circle is not empty
  30.                           // Post : returns the value of the Item at the  
  31.                           //        current position
  32.     int size();           // Pre  : none
  33.                           // Post : returns the number of Items in the circle
  34.     void printCircle();   // Pre  : none
  35.                           // Post : circle is displayed from the current
  36.                           //        position clockwise around the circle;
  37.                           //        Items are displayed tab-separated on  
  38.                           //        one line
  39.     bool empty();         // Pre  : none
  40.                           // Post : returns true if circle is empty
  41.                           //        and otherwise false  
  42.   private:
  43.  
  44.       int length;         // maintains the length of the circle
  45.       struct node {
  46.          Item num;
  47.          node * next;
  48.       } * ring;           // ring points to a circular linked list of
  49.                           // nodes
  50.                           // ring->next is the current position
  51. };
  52.  
  53. #endif


 
circle.cpp que j ai fais.

Code :
  1. #include <iostream>
  2. #include "circle.h"
  3. using namespace std;
  4. circle::circle()
  5. {
  6. length=0;
  7. ring = NULL;
  8. }
  9. circle::~circle()
  10. {
  11. }
  12. circle::circle(const circle & c)
  13. {
  14. }
  15. void circle::insert(Item x)
  16. {
  17. length++;
  18. if (!ring)
  19. {
  20.  ring = new node;
  21.  ring->num = x;
  22.  ring->next = ring;
  23. }
  24. else
  25. {
  26.  node* temp = new node;
  27.  temp->next = ring->next;
  28.  temp->num=x;
  29.  ring->next = temp;
  30.  ring = temp;
  31. }
  32. }
  33. void circle::remove()
  34. {
  35. ring->num = ring ->next->num;
  36. ring->next = ring->next->next;
  37. //node* target = ring->next;
  38. //delete target;
  39. length--;
  40. }
  41. Item circle::getCurrent() { return ring->num; }
  42. void circle::move(int k) { for (int i=0; i<k; i++) ring = ring->next; }
  43. int circle::size() { return length; }
  44. bool circle::empty() { return (length==0); }
  45. void circle::printCircle()
  46. {
  47. for (int i=0; i<length; i++)
  48. {
  49.  cout << ring->num << "\t";
  50.  ring=ring->next;
  51. }
  52. cout << endl;
  53. }


 
avec ca on devra resoudre le pb d ejosephus mais c est pas le pb.
 
question
pour la fonction remove
comme j ai un seul pointeur ring, et que justement c est lui qu on veut deleter.
 
je copie donc le numero de la case apres ring (4) dans ring.
et je "coupe" le chemin en indiquant que ring->next c est ring->next->next.
je diminue la taille de -1 et c est bon.
 
e.g (we c moche)
http://coulix-new.ozforces.com.au/node.jpg
 
bref
est ce que je dois deleter la node en fesant.
node* target = ring->next
et delete node.
?
 
et aussi, copy constructor qu est que j y mais ?

Code :
  1. node* copy;
  2. copy=ring;
  3. return copy;


 :??:  
merci,

Reply

Marsh Posté le 06-03-2004 à 08:14:05   

Reply

Marsh Posté le 06-03-2004 à 08:38:09    

xiluoc a écrit :

circle.h qui nous as etait donne.

Code :
  1. void circle::remove()
  2. {
  3. ring->num = ring ->next->num;
  4. ring->next = ring->next->next;
  5. //node* target = ring->next;
  6. //delete target;
  7. length--;
  8. }


 
est ce que je dois deleter la node en fesant.
node* target = ring->next
et delete node.
?


 
Oui, mais pas comme c'est fait en commentaire dans ta fonction sinon tu vas effacer le node courant. Il faut que tu fasses ton target=ring->next avant de décrocher le noeud de la liste, que tu le décroches et après que tu l'effaces. Aussi, il vaudrait mieux ajouter deux tests. Un premier pour t'assurer que le programmeur utilisant cette classe ne fait pas n'importe quoi et n'essaye pas d'effacer un élément alors que la liste est vide ; un deuxième pour remettre node à NULL lorsque le programmeur efface le dernier élément de la liste (sinon il va avoir des petits soucis lors de son prochain insert).
 

Citation :

et aussi, copy constructor qu est que j y mais ?


 
Il faut que tu y parcoures la liste à copier et que pour chaque élément d'origine, tu en crées un nouveau dans la liste de destination ; le plus simple à coder étant de parcourir la liste d'origine d'un coté et d'utiliser la fonction insert pour chaque item de l'autre.

Reply

Marsh Posté le 06-03-2004 à 08:50:22    

merci,
oui le commentaire etait mal place il vas au debut pour le link et a la fin le delete target.  
 

Code :
  1. void circle::remove()
  2. {
  3. if (length==0) return;
  4. else if (length==1) { delete ring; }
  5. else
  6. {
  7.  node* target = ring->next;
  8.  ring->num = ring ->next->num;
  9.  ring->next = ring->next->next;
  10.  delete target;
  11.  length--;
  12. }
  13. }


 j ai utiliser cette classe pour resoudre josephus,
(au cas ou tu ne le saurai pas)
un cercle de n gas, tu choisis k pour intervalle et tout les k tu remove.
 
y a petit bug je tombe pas sur la bonne personne mais j y travaille =)
 
[3615 my life]
pour info c est notre premier assignement (devoir noter, y en a 4 par semestre et celui ci vaut 4% de la note final) de l unite comp225 ( programmation c++ data structure et algo) seconde annee  a sydney. (macquarie uni)


Message édité par xiluoc le 06-03-2004 à 08:50:50
Reply

Marsh Posté le 06-03-2004 à 09:01:54    

Code :
  1. if (length==1) { delete ring; }


 
Non, non, non. Deux bugs sur cette ligne.

Reply

Marsh Posté le 06-03-2004 à 09:14:41    

hummm  
il reste une node.(ring)
ring->next pointe vers ring  
 
eh ben je la delete non ?
et y a plus rien ah si je dois invoquer le deconstructor de circle peut etre ?
 
inplementation de josephus

Code :
  1. int main()
  2. {
  3. int n,k;
  4. cout << "\tThe Josephus Problem" << endl;
  5. cout << "Please enter values for n and k : ";
  6. cin >> n >> k;
  7. // to fix : error checking
  8. circle c;
  9. for (int i=1; i<=n; i++) c.insert(i);
  10. c.move(1);
  11. c.printCircle();
  12. while (c.size() >1)
  13. {
  14.  c.move(k-1);
  15.  c.remove();
  16.  c.printCircle();
  17. }
  18. cout << "survivor : " << c.getCurrent() << endl;
  19. }

Reply

Marsh Posté le 06-03-2004 à 09:42:14    

xiluoc a écrit :

hummm  
il reste une node.(ring)
ring->next pointe vers ring  
 
eh ben je la delete non ?
et y a plus rien ah si je dois invoquer le deconstructor de circle peut etre ?


 
Quelles seront les valeurs de length et de ring après le delete de ce dernier élément ?

Reply

Marsh Posté le 06-03-2004 à 09:47:24    

oups,
length --;
ring =NULL;
;)

Reply

Marsh Posté le 11-03-2004 à 13:53:43    

:hello: ,
 
j ai dut mal a comprendre le copy constructor, les bouquins que j ai n en parlent pas trop.
 
sinon pour le destructor :

Code :
  1. while (length!=0) { remove(); }


 
<quote>
Il faut que tu y parcoures la liste à copier et que pour chaque élément d'origine, tu en crées un nouveau dans la liste de destination ; le plus simple à coder étant de parcourir la liste d'origine d'un coté et d'utiliser la fonction insert pour chaque item de l'autre.
</quote>
 
je cree un nouveau pointeur ring2 ?
et ensuite j insert un truc du genre :

Code :
  1. for(int i = 0; i <= length; i++)
  2. {
  3. c.insert(ring->data);
  4. ring=ring->next;
  5. }


le pointeur ring vas donc faire un tour complet ni vu ni connu  :whistle:  
Ca serait sympa de m eclaircir un peu sur ce point.
 :hello:  

Reply

Marsh Posté le 12-03-2004 à 07:04:58    

xiluoc a écrit :

:hello: ,
 
j ai dut mal a comprendre le copy constructor, les bouquins que j ai n en parlent pas trop.


 
Le copy constructor sert surtout à deux choses:
- initialiser un objet en une passe à partir d'un objet de la même classe
- copier un objet automatiquement sans faire une copie membre à membre
 
Par exemple, imaginons une méthode de votre classe single:
 

Code :
  1. class single{
  2. ....
  3. void test(single s)
  4. {
  5. }
  6. ....};


 
Lorsque vous appelez la méthode test, si vous n'avez pas défini de copy constructor, comme le paramètre s de type single est passé par valeur, le compilateur fera une copie membre à membre pour vous. En sortie de la fonction, cette copie est détruite. Comme il s'agissait d'une copie membre à membre, cela veut dire que le pointeur ring de votre objet d'origine est maintenant invalide. Faire un copy constructor (correct) permet d'éviter ce genre de bugs.
 
Un exemple pour que cela soit plus clair :
 

Code :
  1. item x,y,z;
  2. single toto, for_bug;
  3. toto.insert(x);
  4. toto.insert(y);
  5. toto.insert(z);
  6. // toto est copié membre à membre à cause du passage par valeur
  7. // et du copy constructor qui n'est pas défini
  8. for_bug.test(toto);
  9. // ici, la copie de toto est détruite
  10. // donc toto.ring est maintenant invalide
  11. // access violation
  12. toto.remove()
  13. // access violation
  14. toto.insert(z)
  15. // access violation...


 
 
 

Citation :

sinon pour le destructor :

Code :
  1. while (length!=0) { remove(); }



 
C'est bon.
 

Citation :

je cree un nouveau pointeur ring2 ?
et ensuite j insert un truc du genre :

Code :
  1. for(int i = 0; i <= length; i++)
  2. {
  3. c.insert(ring->data);
  4. ring=ring->next;
  5. }


le pointeur ring vas donc faire un tour complet ni vu ni connu  :whistle:


 
Il faut que vous utilisiez un autre pointeur (node * ring2=s.ring; par exemple) parce qu'une déclaration correcte du copy constructor sera :

Code :
  1. single(const single & s)
  2. {
  3. //...
  4. }


 
C'est-à-dire que s (c'est l'objet à copier) est une référence vers un objet "constant" et que vous ne pouvez donc pas modifier ses membres. D'où la nécessité d'utiliser un autre pointeur tel que ring2.

Reply

Marsh Posté le 12-03-2004 à 13:01:57    

merci ! pour toute ces explication !
 
je vais expliquer ce que j ai fait, et en meme temps essayer de comprendre pourquoi ca marche pas completement.
 
circle::circle(const circle & c)
si c pointe vers null, alors ma copy aussi.
sinon,
on cree un nouveau pointeur ring_cursor qui pointe vers la meme chose que c.ring (deja la je ne savait pas qu on pouvait acceder a une varible private d un objet en fesant obljet.var)
tant qu on as pas fait le tour de la source,
on insert(ring_cursor->num)
et on avance ring_cursor.
 
 

Code :
  1. circle::circle(const circle & c)
  2. {
  3. if (c.ring==NULL)  ring=NULL;
  4. else {
  5.  node* ring_cursor = c.ring;
  6.  for (int i=0; i <= c.length; i++)
  7.  {
  8.   insert(ring_cursor->num);
  9.   ring_cursor = ring_cursor->next;
  10.  }
  11. }
  12. }


 
pour tester le copy constructor j ai fait ca :
 

Code :
  1. circle c,d;
  2. c.insert(1);
  3. c.insert(2);
  4. c.insert(3);
  5. d=c;
  6. c.printCircle();
  7. d.printCircle();
  8. c.remove();
  9. c.remove();
  10. c.printCircle();
  11. d.printCircle();


 
et helas ... j obtient ca:

Code :
  1. 3       1       2      //c bon (le 3 correspond au pointeur ring)  
  2. 3       1       2      //c bon la copie a bien marche !
  3. 2                      //c bon j enleve le 3 et 1
  4. 2       2       2      // :/


Message édité par xiluoc le 12-03-2004 à 13:05:35
Reply

Marsh Posté le 12-03-2004 à 13:01:57   

Reply

Marsh Posté le 12-03-2004 à 13:06:39    

Code :
  1. if (c.ring==NULL)  ring=NULL;


 
Vous avez un bug sur cette ligne (que vaut length?).
 

Code :
  1. d=c;


 
Ici, vous n'utilisez pas le constructeur par copie mais l'opérateur d'affectation.
 
Pour utiliser le constructeur par copie, il faut faire à la place :
 

Code :
  1. circle d(c);


Message édité par docmaboul le 12-03-2004 à 13:07:16
Reply

Marsh Posté le 12-03-2004 à 13:51:21    

ca y est ca marche! , eh ben j y aurai mis le temps.

Code :
  1. circle::circle(const circle & c)
  2. {
  3. if (c.ring==NULL) 
  4. {
  5.  ring=NULL;
  6.  length =0;
  7. }
  8. else {
  9.  ring = NULL;
  10.  length = 0;
  11.  node* ring_cursor = c.ring;
  12.  while (length != c.length)
  13.  {
  14.   ring_cursor = ring_cursor->next;
  15.   insert(ring_cursor->num);
  16.  }
  17. }
  18. }

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed