Linear data structure

catalogue 1, Linear table and its implementation 1. Repre...
1. Representation of polynomials
2. What is a linear table
3. Sequential storage implementation of linear table
4. Implementation of chain storage of linear list
5. Generalized table
6. Multiple linked list
1. What is a stack
2. Sequential storage implementation of stack
3. Chain storage implementation of stack
4. Stack application: expression evaluation
1. What is a queue
2. Implementation of sequential storage of queues
3. Implementation of chained storage of queue
4. Application example: polynomial addition
5. Multiplication and addition of polynomials

catalogue

1, Linear table and its implementation

1. Representation of polynomials

Method 1: direct representation of sequential storage structure

Method 2: the sequential storage structure represents non-zero items

Method 3: the linked list structure stores non-zero items

2. What is a linear table

3. Sequential storage implementation of linear table

3.1 initialization (create an empty sequence table)

3.2 search

3.3 insertion

3.4 deletion

4. Implementation of chain storage of linear list

4.1 meter length calculation

4.2 search

4.3 insertion

4.4 deletion

4.5 case: reversal of single linked list

5. Generalized table

6. Multiple linked list

2, Stack

1. What is a stack

2. Sequential storage implementation of stack

2.1 an array implements a stack

2.2 an array implements two stacks

3. Chain storage implementation of stack

4. Stack application: expression evaluation

3, Queue

1. What is a queue

2. Implementation of sequential storage of queues

3. Implementation of chained storage of queue

4. Application example: polynomial addition

5. Multiplication and addition of polynomials

5.1 understanding of the meaning of the question

5.2 solution ideas

1, Linear table and its implementation

1. Representation of polynomials

Univariate polynomial and its operation

Univariate polynomial:

Main operations: polynomial addition, subtraction, multiplication, etc

[analysis] key data of polynomial:

Polynomial term n
Various coefficientsAnd index i

Method 1: direct representation of sequential storage structure

Polynomial corresponding to each component of the array:

a[i]: coefficient ai of item xi

For example:

Expressed as:

  Add two polynomials: add the corresponding components of two arrays

Method 2: the sequential storage structure represents non-zero items

Each non-zero term    Two pieces of information are involved: coefficients    And index i  

A polynomial can be regarded as a   A collection of two tuples.

Represented by a structural array: the array component is composed of coefficients The structure composed of index i corresponds to a non-zero term

For example:  and  

  Addition process: you can compare the exponents of the current corresponding terms of two polynomials from scratch

Method 3: the linked list structure stores non-zero items

The linked list stores a non-zero term in the polynomial at each node, including two data fields of coefficient and exponent and one exponential field

Node:

Struct PolyNode { int coef; int expon; Polynomial link; } PolyNode* Polynomial;

[linked list storage form]

2. What is a linear table

  • Linear List: a linear structure consisting of ordered sequences of data elements of the same type

    • The number of elements in the table is called the length of the linear table

    • When a linear table has no elements, it is called an empty table

    • The starting position of a table is called the header, and the ending position of a table is called the footer

  • Abstract data type description of linear table

    • Type name: linear table (List)

    • Data object sets: linear tables   An ordered sequence of elements  

    • Action sets: linear tables , integer i represents position, element , the basic operations of linear table mainly include:

      • 1. List MakeEmpty(): initializes an empty linear table L;

      • 2. ElementType FindKth(int K, List L): returns corresponding elements according to bit order K;

      • 3. int Find(ElementType X, List L): find the first occurrence position of X in the linear table L;

      • 4. void Insert(ElementType X, int i, List L): insert a I new element X before bit order I;

      • 5. void Delete(int i, List L): deletes the elements of the location order I;

      • 6. int Length(List L): returns the length n of linear table L.

3. Sequential storage implementation of linear table

Use the continuous storage space of the array to store the elements in sequence

sruct LNode { ElementType Data[MAXSIZE]; int Last; } LNode L; LNode* PtrL = &L;

Access elements with subscript I: L.Data[i] or PTRL - > data [i]

Length of linear table: L.Last+1 or PTRL - > last + 1

Implementation of main operations

3.1 initialization (create an empty sequence table)

LNode* MakeEmpty() { LNode* PtrL = new LNode(sizeof(struct LNode)); PtrL->Last = -1; return PtrL; }

3.2 search

int Find(ElementType X, List PtrL) { int i = 0; while (i <= PtrL->Last && PtrL->Data[i] != X) { i++; } //If not found, - 1 is returned if (i > PtrL->Last) { return -1; } else if { //Return to storage location when found return i; } }

The average number of successful lookups is (n+1)/2, and the average time performance is O(n).

3.3 insertion

The first   Insert a new element with a value of X at a location

void Insert(ElementType X, int i, List PtrL) { if (PtrL->Last == MAXSIZE - 1) { cout << "Table full" << endl; return; } if (i < 1 || i > PtrL->Last + 2) { cout << "Illegal location" << endl; return; } for (int j = PtrL->Last; j >= i - 1; j--) { PrtL->Data[j + 1] = PtrL->Data[j]; PrtL->Data[i - 1] = X; PrtL->Last++; return; } }

The average number of moves is n/2 and the average time performance is O(n).

3.4 deletion

Delete section of table   Elements at multiple locations

void Delete(int i, List PtrL) { if (i < 1 || i > PtrL->Last + 1) { cout << "The element does not exist" << endl; return; } for (int j = i; j <= PtrL->Last; j++) { PtrL->Data[j - 1] = PtrL->Data[j]; PtrL->Laast--; } return; }

The average number of moves is (n-1)/2, and the average time learning ability is O(n).

4. Implementation of chain storage of linear list

Two logically adjacent elements are not required to be physically adjacent; The logical relationship between data elements is established through "chain".

Therefore, inserting and deleting do not need to move data elements, but only need to modify the "chain".

struct LNode { ElementType Data; List Next; } LNode L; LNode* PtrL = &L;

  Implementation of main operations:

4.1 meter length calculation

int Length(LNode* PtrL) { LNode* p = PtrL; int j = 0; while (p) { p = p->Next; j++; } return j; }

The time performance is O(N).

4.2 search

  • Find by sequence number: FindKth

LNode* FindKth(int K, LNode* PtrL) { LNode* p = PtrL; int i = 1; while (p != NULL && i < K) { p = p->Next; i++; } if (i == K) { return p; } else { return NULL: } }

  • Find by value: find

LNode* Find(ElementType X, LNode* PtrL) { LNode* p = PtrL; while (p != NULL && p->Data != X) { p = p->Next; } return p; }

Average time performance O(N).

4.3 insertion

LNode* Insert(ElementType X, int i, LNode* PtrL) { LNode* p, s; if (i == 1) { s = new LNode(Data = X, Next = PrtL); return s; } p = FindKth(i - 1, PtrL); if (p == NULL) { cout << "parameter i error" << endl; return NULL; } else { s = new LNode(Data = X, Next = PrtL); p->Next = s; return PtrL; } }

The average number of lookups is n/2 and the average time performance is O(n).

4.4 deletion

LNode* Delete(int i, LNode* PtrL) { LNode* p, s; if (i == 1) { s = PtrL; if (PtrL != NULL) { PtrL = PtrL->Next; } else { return NULL; } return PtrL; } p = FindKth(i - 1, PtrL); if (p == NULL) { cout << "non-existent i-1 This element" << endl; return NULL; } else if (p->Next == NULL) { cout << "non-existent i This element" << endl; return NULL: } else { s = p->Next; p->Next = s->Next; return PtrL; } }

The average number of lookups is n/2 and the average time performance is O(n).

4.5 case: reversal of single linked list

  • There is a single linked list L, which performs operations to be reversed for every K nodes

//Pseudo code Ptr reverseL(Ptr head, int K) { cnt = 1; new = head->next; old = new->next; while (cnt < K) { tmp = old->next; old->next = new; new = old; old = tmp; cnt++; } head->next->next = old; return new; }
  • test data

    • A tail does not turn back

    • Boundary test

      • Take the address to the upper and lower bounds

      • Just full reverse

      • K = N full reverse

      • K = 1 without inversion

      • Maximum (the last remaining K - 1 does not reverse), minimum N

    • There are redundant nodes

5. Generalized table

  • Generalized List

    • Generalization of generalized time linear table

    • For linear tables, n elements are basic single elements;

    • In a generalized table, these elements can be not only single elements, but also another generalized table

6. Multiple linked list

  • Multiple linked list: nodes in the linked list may belong to multiple chains at the same time

    • There will be multiple pointer fields of nodes in the multi linked list. For example, the previous example includes two pointer fields: Next and SubList;

    • However, a linked list with two pointer fields is not necessarily a multi linked list, such as a two-way linked list

    • It has a wide range of uses: basically, relatively complex data structures such as trees and graphs can be stored in the form of multiple linked lists

  • example

  • Multiple linked list diagram

  • Indicates that the domain Tag distinguishes header nodes and non-zero element nodes

2, Stack

1. What is a stack

  • What is a stack

    • Stack: a linear table with certain operation constraints; Insert and delete only at one end (stack Top and Top)

    • Insert data: Push

    • Delete data: Pop

    • Last In First Out: Last In First Out (LIFO)

  • Abstract data type description of stack

    • Type name: Stack

    • Data object set: a finite linear table with 0 or more elements

    • Operation table: stack with length of MaxSize , stack element  

      • Stack CreateStack(int MaxSize): generates an empty stack with a maximum length of MaxSize

      • int IsFull(Stack S, int MaxSize): judge whether stack S is full

      • void Push(Stack S): push the element item onto the stack

      • int IsEmpty(Stack S): judge whether stack S is empty

      • ElementType Pop(Stack S): deletes and returns the top element of the stack

  • Suffix expression: the operation symbol is after two operands, such as  

  • Infix expression: the operation symbol is between two operands, such as  

  • Suffix expression evaluation strategy: scan from left to right, process operands and operation symbols one by one, and each operation symbol processes the last two operands on the left;

2. Sequential storage implementation of stack

2.1 an array implements a stack

  • The sequential storage structure of the stack is usually composed of a one-dimensional array and a variable recording the position of the elements at the top of the stack

  • definition

#define MaxSize stores the maximum number of data elements struct SNode { ElementType Data[MaxSize]; int Top; }; SNode* Stack;

  • Push

void Push(Stack PtrS, ElementType item) { if (PtrS->Top == MaxSize - 1) { cout << "Stack full" << endl; return; } else { PtrS->Data[++(PtrS->Top)] = item; return; } }

  • Out of stack

ElementType Pop(Stack PtrS) { if (PtrS->Top == -1) { cout << "Stack empty" << endl; return ERROR; //ERROR is a special value of ElementType, which indicates an ERROR } else { return (PtrS->Data[(PtrS->Top)--]); } }

2.2 an array implements two stacks

  • Two stacks are realized with one array to make the most of the array space. As long as there is space, the stack operation can be carried out; The two stacks grow from both ends of the array to the middle; When the top pointers of two stacks meet, it indicates that both stacks are full.

  • definition

#define MaxSize stores the maximum number of data elements struct DStack { ElementType Data[MaxSize]; int Top1; int Top2; }S; S.Top1 = -1; S.Top2 = MaxSize;

  • Push

void Push(DStack* PtrS, ElementType item, int Tag) { //Tag is used as a flag to distinguish two stacks, with values of 1 and 2 if (PtrS->Top2 - PtrS->Top1 == 1) { cout << "Stack full" << endl; return; } if (Tag == 1) { PtrS->Data[++(PtrS->Top1)] = item; } else { PtrS->Data[--(PtrS->Top2)] = item; } }

  • Out of stack
ElementType Pop(DStack* PtrS, int Tag) { if (Tag == 1) { if (PtrS->Top1 == -1) { cout << "Stack 1 empty" << endl; return NULL; } else { return PtrS->Data[(PtrS->Top1)--]; } } else { if (PtrS->Top2 == MaxSize) { cout << "Stack 2 empty" << endl; return NULL; } else { return PtrS->Data[(PtrS->Top2)++]; } } }

3. Chain storage implementation of stack

  • The chain storage structure of stack is actually a single chain list, which is called stack chain; Insert and delete operations can only be performed at the Top of the stack chain, and the Top pointer is at the head of the list; A head node can be set at the head of the stack chain. At this time, the head pointer will point to the head node; Generally, the data field of the head node is meaningless. It is set up for the unity and convenience of operation.

  • definition

struct SNode { ElementType Data; SNode* Next; } typedef SNode* Stack;

  • Create chained stack

Stack CreateStack() { Stack S = new SNode; S->Next = NULL; return s; }

  • Judge whether it is empty

int IsEmpty(Stack S) { return (S->Next == NULL); }

  • Push

void Push(ElementType item, Stack S) { Stack TmpCell = new SNode; TemCell->Element = item; TemCell->Next = S->Next; S->Next = TmpCell; }

  • Out of stack

ElementType Pop(Stack S) { Stack FirstCell; ElementType TopElem; if (IsEmpty(S)) { cout << "Stack empty" << endl; return NULL: } else { FirstCell = S->Next; S->Next = FirstCell->Next; TopElem = FirstCell->Element; return TopElem; } }

4. Stack application: expression evaluation

  • How to convert infix expression into suffix expression (read each object of infix expression from beginning to end and treat different objects according to different situations)

    • Operand: direct output;

    • Left bracket: push into stack;

      • When the left bracket is outside the stack, the priority is the highest;

      • When the left bracket is in the stack, the priority is the lowest;

    • Right bracket: pop up the operator at the top of the stack and output it until it encounters the left bracket (out of the stack, no output);

    • Operator:

      • If the priority is greater than the top of the stack operator, press it on the stack;

      • If the priority is less than or equal to the stack top operator, pop up the stack top operator and output it; Then compare the new stack top operator until it is higher than the priority of the stack top operator, and then press the operator on the stack;

    • If all objects are processed, the operators remaining in the stack are output together;

  • example

  • Other applications of stack:

    • Function call and recursive implementation

    • Depth first search

    • Backtracking algorithm

3, Queue

1. What is a queue

  • What is a queue

    • Queue: a linear table with certain operation constraints; Insert and delete operations can only be inserted at one end and deleted at the other end

    • Data insertion: queued (Add Q)

    • Data deletion: out of queue (Delete Q)

    • FIFO: FIFO

  • Abstract data type description of queue

    • Type name: Queue

    • Data object set: a finite linear table with zero or more elements

    • Action set: queue with length MaxSize , queue element  

      • Queue Create(int MaxSize): generates an empty queue with a length of MaxSize

      • int IsFullQ(Queue Q, int MaxSize): judge whether queue q is full

      • void AddQ(Queue Q, ElementType item): insert the data element item into queue Q

      • int IsEmptyQ(Queue Q): judge whether queue Q is empty

      • ElementType DeleteQ(Queue Q): deletes the queue header data element from the queue and returns it

2. Implementation of sequential storage of queues

  • The sequential storage structure of a queue is usually composed of a one-dimensional array, a variable front that records the position of the head element of the queue and a variable rear that records the position of the tail element of the queue.

A normal work queue

Sequential queue

The structure can be recycled, and a corresponding position should be vacated as the space with the position of - 1

  • definition

#define MaxSize stores the maximum number of data elements struct QNode { ElementType Data[MaxSize]; int front; int rear; }; typedef QNode* Queue;

Here, we use the technique of modulus to realize the queue of sequential ring structure

  • Out of queue

ElementType DeleteQ(Queue PtrQ) { if (PtrQ->rear == PtrQ->front) { cout << "queue is empty" << endl; return ERROR; } else { PtrQ->front = (PtrQ->front + 1) % MaxSize; return PtrQ->Data[PtrQ->front]; } }

3. Implementation of chained storage of queue

  • The chained storage structure of queue can be realized by a single linked list; Insert and delete operations are carried out at both ends of the linked list, front at the head of the linked list and rear at the tail of the linked list.

  • definition

struct Node { ElementType Data; struct Node* Next; }; struct QNode { Node* front; Node* rear; }; typedef QNode* Queue;

  • Create chained queue

Queue creatQueue() { Queue PtrQ; return PtrQ; }

  • Out of queue

ElementType DeleteQ(Queue PtrQ) { Node* FrontCell; ElementType FrontElem; if (PtrQ->front == NULL) { cout << "queue is empty" << endl; return ERROR; } FrontCell = PtrQ->front; if (PtrQ->front == PtrQ->rear) { PtrQ->front = NULL; PtrQ->rear = NULL; } else { PtrQ->front = PtrQ->front->Next; } FrontElem = FrontCell->Data; return FrontElem; }

  • Queue

void AddQ(ElementType item, Queue PtrQ) { Node* RearCell; RearCell->Data = item; RearCell->Next = NULL; if (PtrQ->front == PtrQ->rear) { PtrQ->front = RearCell; PtrQ->rear = RearCell; return; } PtrQ->rear->Next = RearCell; PtrQ->rear = RearCell; }

4. Application example: polynomial addition

Main idea: add the term coefficients of the same index, and copy the rest

Case: a one-way linked list without leading nodes is used to arrange the items in an exponentially decreasing order

Algorithm idea: two pointers P1 and P2 respectively point to the first node of the two polynomials and keep cycling:

  • P1 - > expon = = P2 - > expon: coefficient addition. If the result is not 0, it will be used as the coefficient of the corresponding term of the result polynomial; At the same time, P1 and P2 point to the next item respectively;

  • P1 - > expon > P2 - > expon: store the current term of P1 into the result polynomial and point P1 to the next term;

  • P1 - > expon < P2 - > expon: store the current term of P2 into the result polynomial and point P2 to the next term;

  • When a polynomial is processed, all nodes of another polynomial are copied into the result polynomial in turn.

  • definition

struct PolyNode { int coef; int expon; PolyNode* Next; }; typedef PolyNode* Polynomial; Polynomial P1, P2;

  • Body function

Polynomial PolyAdd(Polynomial P1, Polynomial P2) { Polynomial front, rear; rear = new PolyNode; front = rear; int sum; //When neither P1 nor P2 is empty, it is always executed while (P1 && P2) { //Compare compare size switch (compare(P1->expon, P2->expon)) { //If the index of P1 is large, return 1 case 1: attach(P1->coeef, P1->expon, &rear); //Modify the P1 direction and proceed to the next step P1 = P1->Next; break; //If the index of P2 is large, return - 1 case -1: attach(P2->coef, P2->expon, &rear); //Modify the P2 direction and proceed to the next step P2 = P2->Next; break; //If the exponents of P1 and P2 are equal, 0 is returned case 0: sum = P1->coef + P2->coef; //If the coefficient addition is not 0, a new node is created if (sum != 0) { attach(sum, P1->expon, &rear) } P1 = P1->Next; P2 = P2->Next; break; } } //Unfinished polynomial for (; P1; P1 = P1->Next) { attach(P1->coef, P1->expon, &rear); } for (; P2; P2 = P2->Next) { attach(P2->coef, P2->expon, &rear); } //Set the linked list point of the last node to NULL rear->Next = NULL; //Discard the empty node and point directly to the first node of the polynomial front = front->Next; return front; }

  • Other functions

void attach(int c, int e, Polynomial* pRear) { //The prar here is equivalent to a secondary pointer //Create a new node Polynomial p = new PolyNode; //Assign values to new nodes p->coef = c; p->expon = e; p->Next = NULL; //Let the pointer field of the previous node point to the new node //Modify the direction of the rear (*pRear)->Next = p; *pRear = p; }

5. Multiplication and addition of polynomials

5.1 understanding of the meaning of the question

  • Design function to find the product and sum of two univariate polynomials respectively

5.2 solution ideas

  • Solution idea

    • 1. Polynomial representation

    • 2. Procedural framework

    • 3. Read polynomial

    • 4. Additive implementation

    • 5. Multiplication implementation

    • 6. Polynomial output

  • 1. Polynomial representation

    • Array:

      • Simple programming and easy debugging

      • The array size needs to be determined in advance

      • A better implementation method is dynamic array

    • Linked list:

      • Strong dynamic

      • The programming is slightly complex and debugging is difficult

      • This time, it is represented by linked list

    • Data structure design

typedef PolyNode* Polynomial; struct PolyNode { int coef; int expon; Polynomial Next; }

2. Program framework construction

  • Functions to be designed

    • Read a polynomial

    • Multiplication of two polynomials

    • Addition of two polynomials

    • Polynomial output

  • program

int main () { Polynomial P1, P2, PP, PS; P1 = readPoly(); P2 = readPoly(); PP = mult(P1, P2); printPoly(PP); PS = add(P1, P2); printPoly(PS): return 0; }

3. How to read polynomials

  • Initial value of real

    • 3.1 the initial value of rear is NULL; Judge whether the real is NULL in the attach function;

    • 3.2 real points to an empty node; In this way, the function does not need to make judgment. This method is adopted this time

  • readPoly function

Polynomial readPoly() { Polynomial P, rear; int c, e, n; P = new PolyNode; P->Next = NULL; rear = P; cout << "The number of terms of the polynomial is: " << endl; cin >> n; cout << "Enter in the order of power exponent from large to small: " << endl; while (n--) { cout << "Please enter the coefficient and index of this item respectively: " << endl; cin >> c; cin >> e; attach(c, e, rear); } P = P->Next; return P; }

  • attach function
void attach(itn c, int e, Polynomial& rear) { Polynomial P = new PolyNode; P->c = c; P->e = e; P->Next = NULL; rear->Next = P; rear = P; }

4. How to add two polynomials

  • add function

Polynomial add(Polynomial P1, Polynomial P2) { Polynomial P = new PolyNode; P->Next = NULL: Polynomial rear = P; int sum; while (P1 && P2) { switch(compare(P1->expon, P2->expon)) { case 1: attach(P1->coef, P1->expon, rear); P1 = P1->Next; break; case -1: attach(P2->coef, P2->expon, rear); P2 = P2->Next; break; case 0: sum = P1->coef + P2->coef; if (sum) { attach(sum, P1->expon, rear); P1 = P1->Next; P2 = P2->Next; } break; } } while(P1) { attach(P1->coef, P1->expon, rear); P1 = P1->Next; } while(P2) { attach(P2->coef, P2->expon, rear); P2 = P2->Next; } P = P->Next; return P; }

5. How to multiply two polynomials

  • method

    • Converting multiplication to addition; Multiply the current term of P1 by P2 polynomial and add it to the result polynomial

    • Insert item by item; Multiply P1 current term by P2 current term and insert it into the result polynomial. The key is to find the insertion position; The initial result polynomial is obtained by multiplying the first term of P1 by P2; The method adopted this time;

  • mult function

Polynomial mult(Polynomial P1, Poltnomial P2) { if (!P1 || !P2) { return NULL; } Polynomial P, rear, t1, t2; int c, e; P = new PolyNode; P->Next = NULL; rear = P; t1 = P1; t2 = P2; while (t2) { //Create initial result polynomial attach(t1->coef * t2->coef, t1->expon + t2->expon, rear); t2 = t2->Next; } t1 = t1->Next; while (t1) { t2 = P2; rear = P; while (t2) { c = t1->coef * t2->coef; e = t1->expon + t2->expon; //Find out that the value of rear - > next - > expon is less than or equal to e while (rear->Next && rear->Next->expon > e) { rear = rear->Next; } //Judge whether it is less than or equal to if (rear->Next && rear->Next->expon == e) { //Judge whether the coef value is zero if (rear->Next->coef + c) { rear->Next->coef += c; } else { rear->Next = rear->Next->Next; } } else { //If it is less than, create a new node to insert Polynomial t = new PloyNode; t->coef = c; t->expon = e; t->Next = rear->Next; rear->Next = t; } t2 = t2->Next; } t1 = t1->Next; } P = P->Next; return P; }

  • 6. How to output polynomials

void printPoly(Polynomial P) { if (!P) { cout << "0" << endl; return; } while (P) { cout << P->coef << " " << P->expon << " "; P = P->Next; } cout << endl; }

22 October 2021, 20:31 | Views: 1968

Add new comment

For adding a comment, please log in
or create account

0 comments