Single-chain table for Data Structure Learning

Source: Internet
Author: User
Tags table definition

From: happcock Forum

Node

# Ifndef node_h
# Define node_h

Template Class node // Single-Chain node class
{
Public:
Type data;
Node * Link;
Node (): Data (type (), Link (null ){}
Node (const type & item): Data (item), Link (null ){}
Node (const type & item, node * P): Data (item), Link (p ){}
};
# Endif

[Note] because there are too many places to use this structure in the data structure, if we use the data structure method to declare friends, we do not know how long the declaration is than the class itself. It is better to open members. In fact, this structure is only the struct in C. Except for convenient initialization, no method is required. The original book is superfluous. The public part of the linked list does not return the node or node * function. Therefore, other classes cannot use this open interface to operate nodes in the linked list.

[Important changes] The default constructor of the original book is node (): Data (null), Link (null ){}. I used to write it as well. As a result, when I expanded it, I found this was wrong. When type is a structure rather than a simple type (INT ,......), NULL values cannot be simply assigned. In this way, the defined template can only be used for a few simple types. Obviously, the default Type constructor should be called here. This also requires that the classes used here must have Default constructors. The default constructor is used to construct the linked list. Of course, the linked list with table header nodes is agreed here. If you do not take the lead node, please think for yourself.

[Idle talk] Please do not have any doubt about int * P = new int (1); in fact, int can also be seen as a class.

Single-chain table class definition and implementation

# Ifndef list_h
# Define list_h
# Ifndef ture
# Define ture 1
# Endif
# Ifndef false
# Define false 0
# Endif

Typedef int bool;

# Include "node. H"

Template Class list // single-chain table definition
{
// Basically, the member functions without parameters operate on the current node, that is, the current node.
// The "1st nodes" in the table is considered as 0th nodes. Note that when the table length is 1, The Last node is 0th nodes.
Public:
List () {First = current = last = new node ; Prior = NULL ;}
~ List () {makeempty (); Delete first ;}
Void makeempty () // empty table
{
Node * Q;
While (first-> link! = NULL)
{
Q = first-> link;
First-> link = Q-> link;
Delete Q;
}
Initialize ();
}
Bool isempty ()
{
If (first-> link = NULL)
{
Initialize ();
Return ture;
}
Else return false;
}
Int length () const // calculate the length of a single-chain table with table header nodes
{
Node * P = first-> link;
Int COUNT = 0;
While (P! = NULL)
{
P = p-> link;
Count ++;
}
Return count;
}
Type * Get () // return the address of the data domain of the current node
{
If (current! = NULL) return response T-> data;
Else return NULL;
}
Bool put (type const & Value) // change the data of the current node to value
{
If (current! = NULL)
{
Current-> DATA = value;
Return ture;
}
Else return false;
}

Type * getnext () // return the address of the data domain of the next node of the current node, without changing the current
{
If (current-> link! = NULL) return response T-> link-> data;
Else return NULL;
}
Type * Next () // move current to the next node and return the data domain address of the node.
{
If (current! = NULL & Current-> link! = NULL)
{
Prior = current;
Current = Current-> link;
Return response T-> data;
}
Else
{
Return NULL;
}
}
Void insert (const type & Value) // insert a node behind the current node without changing the current
{
Node * P = new node (Value, current-> link );
Current-> link = P;
}
Bool insertbefore (const type & Value) // insert a node before the current node, without changing the current, changing the prior
{
Node * P = new node (Value );
If (Prior! = NULL)
{
P-> link = current;
Prior-> link = P;
Prior = P;
Return ture;
}
Else return false;
}

Bool locate (int I) // move current to node I
{
If (I <=-1) return false;
Current = first-> link;
For (Int J = 0; current! = NULL & J <I; j ++, current = Current-> link)
Prior = current;
If (current! = NULL) return ture;
Else return false;
}

Void first () // move current to the header
{
Current = first;
Prior = NULL;
}
Void end () // move current to the end of the table
{
If (last-> link! = NULL)
{
For (; Current-> link! = NULL; current = Current-> link)
Prior = current;
Last = current;
}
Current = last;
}

Bool find (const type & Value) // move current to a node with data equal to value
{
If (isempty () return false;
For (current = first-> link, prior = first; current! = NULL & Current-> data! = Value;
Current = Current-> link)
Prior = current;
If (current! = NULL) return ture;
Else return false;
}
Bool remove () // Delete the current node. Current points to the next node. If current is at the end of the table, current = NULL
{
If (current! = NULL & Prior! = NULL)
{
Node * P = current;
Prior-> link = p-> link;
Current = p-> link;
Delete P;
Return ture;
}
Else return false;
}

Bool removeafter () // Delete the next node of the current node without changing the current
{
If (current-> link! = NULL & current! = NULL)
{
Node * P = Current-> link;
Current-> link = p-> link;
Delete P;
Return ture;
}
Else return false;
}

Friend ostream & operator <(ostream & STRM, list & L)
{
L. First ();
While (L. Current-> link! = NULL) STRM <* L. Next () <"";
STRM <Endl;
L. First ();
Return STRM;
}

Protected:

/* Is mainly added for efficient queuing algorithms. Because insert (), remove (), removeafter () may change last but does not change last, this algorithm is incorrect if it is in public unless it is not used. However, in addition to being very useful in the queue, last is rarely used in other scenarios. It is not necessary to reduce the efficiency of insert () and remove () for this purpose, so we put this part in protected, in fact, it is mainly used to inherit from the queue */void lastinsert (const type & value)

{
Node * P = new node (Value, last-> link );
Last-> link = P;
Last = P;
}

Void initialize () // reset the pointer when the table is empty.
{
Current = last = first;
Prior = NULL;
}

// The return type of these functions is node. Pointer, which is an interface to extend the list Function
 
Node * Pget ()
{
Return Current;
}
Node * Pnext ()
{
Prior = current;
Current = Current-> link;
Return Current;
}

Node * Pgetnext ()
{
Return Current-> link;
}

Node * Pgetfirst ()
{
Return first;
}

Node * Pgetlast ()
{
Return last;
}

Node * Pgetprior ()
{
Return prior;
}

Void putlast (node * P)
{
Last = P;
}
// This Part of the insert/delete function does not create or delete nodes. It is an in-situ operation interface.

Void insert (node * P)
{
P-> link = Current-> link;
Current-> link = P;
}
Void insertbefore (node * P)
{
P-> link = current;
Prior-> link = P;
Prior = P;
}

Void lastinsert (node * P)
{
P-> link = NULL;
Last-> link = P;
Last = P;
}

Node * Premove ()
{
If (current! = NULL & Prior! = NULL)
{
Node * P = current;
Prior-> link = Current-> link;
Current = Current-> link;
Return P;
}
Else return NULL;
}

Node * Premoveafter ()
{
If (current-> link! = NULL & current! = NULL)
{
Node * P = Current-> link;
Current-> link = Current-> link;
Return P;
}
Else return NULL;
}

PRIVATE:
List (const list & L );
Node * First, * Current, * Prior, * last;
// Try not to use last. Use end () to make the pointer last correct.
};

# Endif

[Note] I put the iterator function of the cursor class of the original book in the Linked List class, blocking the interfaces with the return values of node and node * types. This kind of linked list is simple and practical, the expansion performance is also good.

When I finished my homework, I found the advantages of the original book practice, that is, my shortcomings. If you use the definition of the original book, you only need to write the corresponding function implementation to complete a function. In my definition, you must first assign a class and then use this function as a member or friend. However, this comparison is not a more reasonable definition than I do. First, there are not many situations where in-situ operations are used, and post-book homework is only a special case. In other words, the definition in the book is only more practical for post-book homework. Secondly, when using a linked list, we usually only use a few functions, such as insert, delete, retrieve data, and search. I have enough definitions. When a software is completed, the expansion function of the linked list is clearly defined in the design stage. At this time, a new class can be derived for use in the entire software, which is more advantageous for the overall planning. For a single linked list operation, it is better understood as a member function. That is to say, my definition is flexible.

Single-chain table Application

Some people have suggested separating the linked list and linked list locations. The C ++ standard library does this. But for beginners, a class is better than two classes. I don't know whether the program in this part of the book is debugging or not, but I absolutely cannot understand such statements:

Listnode * PA, * pb, * PC, * P;
Listiterator AIter (ah. Poly );
Listiterator Biter (ah. Poly );
Pa = pc = aIter. First (); Pb = P = biter. First ();
.............................
Pa-> coef = pa-> coef + Pb-> coef;
P = Pb; Pb = biter. Next (); Delete P;

What does Pa, Pb, and P point? You make it clear that listnode Such a node. However, according to the definition in the original book, listiterator: First () and other functions return pointers to data domains. How can they assign values directly? In the following mess, Pb points to the region and directly breaks down the data members of the term, that is, it points to the term structure; then let the listnode Type pointer P points to this term structure, and finally deletes this structure. Oh, my God, listnode The data field of such a node is deleted!

If you start with basic node operations, no one will be confused. But because there is another class, many things will be neglected. Therefore, I do not doubt the practice of the standard library, but for beginners, it is best to operate only one class at a time. I completed the program again based on my definition. I don't like the polynomial addition (+), polyA + polyb in the in-situ operation, and then B will just crash, and a will be a bunch more (or maybe a bunch less ); why didn't you see any changes in J and K when you made intj + intk. In this way, it is better to reload "+" as polyA. Add (polyb) or polyadd (polyA, polyb ).

  Definition and implementation of Polynomial

# Ifndef polynomial_h
# Define polynomial_h

# Include "list. H"
Class term
{
Public:
Int coef;
Int exp;
Term (): coef (0), exp (0 ){}
Term (int c, int e): coef (C), exp (e ){}
Term (int c): coef (C), exp (0 ){}
};

Class polynomial: List
{
Public:
Void input ()
{
Cout <Endl <"coefficients and indexes of input polynomials ";
Cout <Endl <"NOTE: Enter items in descending order, and the input coefficient 0 indicates the end" <Endl;
Int coef, exp;
For (INT I = 1; I ++)
{
Cout <"no." <I <"coefficient :";
Cin> coef;
If (coef)
{
Cout <"index :";
Cin> exp;
Term term (coef, exp );
Insert (TERM );
}
Else break;
}
}
Void print ()
{
Cout <Endl;
First ();
If (! Isempty ())
{
Term * P = next ();
Cout <p-> coef;
If (p-> exp)
{
Cout <"X ";
If (p-> exp! = 1) cout <"^" <p-> exp;
}
While (next ()! = NULL)
{
P = get ();
If (p-> coef> 0) cout <"+ ";
Cout <p-> coef;
If (p-> exp)
{
Cout <"X ";
If (p-> exp! = 1) cout <"^" <p-> exp;
}
}
}
Cout <Endl;
}
Friend void polyadd (Polynomial & polyA, Polynomial & polyb)
{
Node * PA, * pb;
PolyA. First (); polyb. First ();
Pa = polyA. pnext (); Pb = polyb. pnext ();
While (Pa! = NULL & Pb! = NULL)
{
If (Pa-> data. Exp = Pb-> data. exp)
{
Pa-> data. coef = pa-> data. coef + Pb-> data. coef;
Polyb. Remove ();
If (! Pa-> data. coef) polyA. Remove ();
Else polyA. pnext ();
}
Else
{
If (Pa-> data. Exp> Pb-> data. exp)
{
Polyb. premove ();
PolyA. insertbefore (PB );
}
Else if (Pa-> data. Exp <Pb-> data. exp) polyA. pnext ();
}
Pa = polyA. pget (); Pb = polyb. pget ();
}
If (Pa = NULL)
{
PolyA. pgetprior ()-> link = Pb;
Polyb. pgetprior ()-> link = NULL;
}
}
};
# Endif

[Note] For polynomials, we usually write them in descending order, so I need to input them in descending order. However, for addition, ascending order is indeed more convenient, so it actually becomes ascending when it comes to the interior. For the output format (I do not like this when I start from C), try to take care of the habit, but when the coefficient of a very few is 1, it will still output the coefficient, I really don't want to make complicated output functions that are not included in a practical application. For my convenience, the output is in ascending order. Please include more. The test program is not given. It is very simple. In the remainder of the article, I will complete the overload of the unary polynomial "+" "-" × "" = "-Why is there no" success "? I am not doing anything about this kind of operation, it is even more difficult to compile, and I still remember the pain of writing a multi-byte division program by means of compilation. In the next article, you can write a = B + C * D; A. Print ().

Here will be some examples of heavy-load operators. Our job will be to make polynomial operations look more in line with writing habits. To do this, I think I changed the "+" of the original book to polyadd () without authorization. I always have to explain it to me.

Next we will reload the assignment operation for a single-chain table. Please add this part to the public part of the List class. Indeed, this part can also be implemented in the polynomial class. However, copying a polynomial is actually copying a single-chain table. Instead of simply assigning values to a polynomial, it is better to assign values to a single-chain table, share all the derived classes.

Operator = (const list & L)
{
Makeempty ();
For (node * P = L. First-> link; P! = NULL; P = p-> link) lastinsert (p-> data );
}

Remember the list (const list & L? I was afraid of getting it into trouble and disabled it directly. Now = can be used, for this syntax list B = A; By the way, it's done. Now we can put it from private to public.

List (const list & L)
{
First = current = last = new node ; Prior = NULL;
For (node * P = L. First-> link; P! = NULL; P = p-> link) lastinsert (p-> data );
}

Finally, we can write a = B + C * D.

Friend polynomial operator + (Polynomial & polyA, Polynomial & polyb)
{
Polynomial Tempa = polyA; polynomial tempb = polyb;
Polyadd (Tempa, tempb );
Return Tempa;
}

Friend polynomial operator * (Polynomial & polyA, Polynomial & polyb)
{
Node * PA = polyA. pgetfirst ()-> link;
Node * Pb = polyb. pgetfirst ()-> link;
Polynomial polytempa, polytempb;
Int coef, exp;
If (Pa = NULL | Pb = NULL) return polytempa;
For (Pa = polyA. pgetfirst ()-> link; pa! = NULL; Pa = pa-> link)
{
For (PB = polyb. pgetfirst ()-> link; Pb! = NULL; Pb = Pb-> link)
{
Coef = pa-> data. coef * pb-> data. coef;
Exp = pa-> data. Exp + Pb-> data. Exp;
Term term (coef, exp );
Polytempb. lastinsert (TERM );
}
Polyadd (polytempa, polytempb );
Polytempb. initialize ();
}
Return polytempa;
}

[Note] Obviously, I am lazy in "+" processing, but this is the most convenient. As long as the multiplication part refers to manual operations, it is still very simple and I will not explain it. For "-", you can first complete an algorithm like-a, and then complete it with addition, if you are as lazy as I do, it is very likely that you will do this kind of thing-A =-1 × A. It is really not recommended and ultra-low efficiency. For Division, if you write multi-byte division by means of aggregation (similar to manual calculation), you can also use the sample image gourd, but you must first complete "-". If you want to write it for a long time, you can finish it. Here you understand the importance of in-situ addition. These operations are actually implemented by it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.