Postgraduate data structure-linear table

The basic concept and realization of linear table

1. Definition of linear table

A linear table is a finite sequence of data elements with the same characteristics .

The number of elements is called the length of the linear table, n (n> = 0) means, n = 0 (empty table)

2. Logical characteristics of linear tables

There is only one header element and only one tail element. There is no predecessor in the header and no successor in the tail. Except for the header and footer, the other elements have only one direct precursor and only one direct successor.

3. Storage structure of linear table

There are two kinds of sequential storage structure (sequence list) and chain storage structure (linked list).

Sequence table

Continuous storage, sequential storage.

Linked list

Not only the information of the elements, but also the information of the logical relationship (the address information of the subsequent nodes).

Comparison of two storage structures

Sequence table:

Random access feature, occupying continuous storage space.

Insert: Need to move multiple elements.

Linked list:

Random access is not supported, the storage space utilization rate is slightly lower than the sequence table, and dynamic storage space allocation is supported.

Insert: No need to move elements.

Five forms of linked lists:

  1. Single list:

    Single linked list with head node (no information stored in head node): head-> next == Null, the linked list is empty.

    Singly linked list without head: head == Null, the linked list is empty.

  2. Double linked list: one more precursor node

  3. Circular singly linked list:

    The last pointer field (null pointer) of the singly linked list points to the first node. If the loop node wears a head node, the last pointer field (null pointer) points to the head node.

  4. Circular double linked list:

    head == Null, the circular double linked list without head node is empty.

    Leading node, in the empty state, head-> next and head-> prior must be equal to head.

    Any one of the following four sentences can be true to determine that the circular doubly linked list is empty.

    head->next==head;
    head->priot==head;
    head->next==head && head->priot==head;
    head->next==head || head->priot==head;
    
  5. Static linked list

    The pointer indicates the address of the next element in the linked list in the array.

    Compared with the sequence table, the advantage is that it is easy to insert and delete.

Note: The comparison of the sequence table and the linked list is often taken in the postgraduate examination, and a comprehensive answer is given.

Space-based comparison

  1. Distribution of storage methods:

    The storage space of the sequence table is allocated once, and the storage space of the linked list is allocated multiple times.

  2. Storage density (storage density = storage amount occupied by the node value domain / total storage amount occupied by the node structure)

    The storage density of the sequence table = 1, and the storage density of the linked list <1 (because there is a pointer field in the node)

Time-based comparison

  1. Access method

    The sequence table can be randomly accessed;

    The linked list can only be accessed sequentially (traversing the previous element)

  2. Number of elements to move when inserting / deleting:

    The sequence table needs to move nearly half of the elements on average;

    The linked list does not need to move elements, only the pointer needs to be changed.

N sequence table and delete elements inserted and complexity analysis is applied:

  • Find the probability

    Random insertion positions, n insertion positions, insertion probability at any position p = 1 / n

  • The number of elements that need to be moved at the corresponding position

    After inserting the ith element, move the ni element.

  • Mathematical expectation E of moving elements:

    E = p (n + (n-1) + (n-2) + …… + 0) = (n-1) / 2; O (n)

    2.2 Structure definition and basic operation of linear table

    Structure definition of linear table

    #define maxSize 100
    

    1. Structure definition of sequence table

    typedef struct{
        int data[maxSize];
        int length;
    }Sqlist;
    

    Note: The definition of the most linear table used in the exam is the following form (because of simplicity):

    int A[maxSize];
    int n;//长度为n
    

    2. Definition of singly linked list nodes

    typedef struct LNode{
    int data;
    struct LNode* next;
    }LNode;

    Recommend this. The yellow lines are as good as written.

    3. Definition of doubly linked list

    typedef struct LNode{
    	int data;
    	struct LNode* prior;
    	struct LNode* next;
    }LNode;
    

    Note: When allocating the space of a linked list node, define a pointer that points to the node. The name of this pointer is often used as the name of the node.

    LNode *A = (LNode*)malloc(sizeof(LNode))

    int p = (int)malloc(sizeof(int))

    typedef struct node{
        int x;
        int y;
    }node;
    int p = (int)malloc(sizeof(int));//ok
    node n = (node)malloc(sizeof(node));//不ok
    node no = new node;//不ok
    node *No = new node[5];//ok
    //上述几个不ok得原因没有想通。
    

    The difference between '*' and '->':

    Structure variable component taken by '.'

    LNode a;
    a.data;
    

    The pointer to the structure variable takes the component with '->'

    LNode *b;
    b->data;
    //(*b)就变成了结构体变量可以用'.'
    (*b).data;
    

    Description and explanation:

    "P points to q", p refers to a pointer because p is both a pointer name and a node name,But the node cannot point to the node, So p refers to the pointer. Another example is "use function free () to free p's space". At this time, p refers to the node, because p is both a pointer name and a node name , but the storage space required by the pointer variable itself is allocated by the system without requiring the user to call the function free()Release, only the storage space allocated by the user needs to be released by the user, so p refers to the node.

    Supplement: (For supplement only, to facilitate deeper understanding.)

    Some classmates may have the same doubts as me. This LNode, in the main function, I do n’t declare it as a LNode * pointer, I must try to declare it as LNode;

    Our conclusion through the code is:Indeed the node cannot point to the node, Because the next attribute in Lnode is a pointer, we can only let the pointer of LNode * point to LNode * next (practice knows!);

    #include <iostream>
    #include<stdlib.h> 
    using namespace std;
    typedef struct LNode{
        int data;
        struct LNode* next;
    }LNode;
    void creat_LNode(LNode &L);
    void print(LNode L);
    int  main() {
        LNode L;
        creat_LNode(L);
        print(L);
        return 0;
    }
    void creat_LNode(LNode &L){
        LNode *temp = &L;
        for(int i =0;i<10;i++){
            temp->data = i;
            LNode* temp2 = (LNode*)malloc(sizeof(sizeof(LNode)));
            temp->next = temp2;
            temp = temp2;
        }
        temp->next = NULL;
        //free(temp);此处不能free();
    }
    void print(LNode L){
        LNode *temp = &L;
        while(temp->next!=NULL){
            cout<<temp->data<<" ";
            temp = temp->next;
        }
    }
    

    Initialization of the sequence table:

    void initList(Sqlist &L){
    	L.length = 0;
    }
    

    "Analysis of Quotes &":

    Sequence table insertion: After inserting e at position p, p returns 0 incorrectly.

    void insertElem(Sqlist &L,int p,int e);

    '&' Is a quote, don't understand it as an address, Because L itself needs to be changed, use a reference to bring the modified value back. If you do not need to quote, the modified value in the function cannot be taken back.

    //p的检查
    if(p<0 || p>L.length || L.length == maxSize)
        return 0;
    

    Linked list insertion:

    Linked tail insertion x

    void insertElem(LNode *L,int x)

    We have modified the singly linked list L, but it is not useful&L

    void insertElem(LNode* &L,int x);

    The change of L internal data has nothing to do with == & ==.

    A reference is added to allow the pointer of the L pointer to be modified, and then it is brought back to the main function.

    If no reference is added, even if we insert the function and let L repoint to a new pointer, the modified value of L cannot be brought into the main function. For example: In the following print () function, the function has been modified L=L->next, and the modified value is not brought back.

    #include <iostream>
    using namespace std;
    typedef struct LNode{
        int data;
        struct LNode* next;
    }LNode;
    void insertElem(LNode *L,int x){
        while(L->next!=NULL){
            L=L->next;
        }
        //此时L的下一个为NULL
        L->next = (LNode*)malloc(sizeof(sizeof(LNode)));
        L->next->data = x;
        L->next->next = NULL;
    }
    void print(LNode *L){
        while (L->next!=NULL){
            L = L->next;
            cout<<L->data<<" ";
        }
        cout<<endl;
    }
    int  main() {
        LNode *L;
        L->data = -1;//头结点
        L->next = NULL;
        for(int i=0;i<10;i++){
            insertElem(L,i);
        }
       print(L);
        return 0;
    }
    

    Inversion problem (408 important test sites)

    void reverse(int a[],int left,int right,int k){
    	int temp;
        for(int i=left,j=right;i<left+k && i<j;i++,j--){
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    }
    
  1. The k (k <n) elements of the front end of the array of length n are reversed to the back end of the array, the data is not lost, and the position of the remaining elements does not matter.

    reverse(a,0,n - 1,k);

  2. The k (k <n) elements at the front end of the array of length n are moved to the back end of the array in the original order, the data is not lost, and the position of the remaining elements does not matter.

    The process of k first and then 1 in reverse order

    reverse(a,0,k-1,k);

    reverse(a,0,n-1,k);

  3. The elements (X 0 , X 1 , ..., X n-1 ) in the array become (X p , X p + 1 , ..., X n-1 , X 0 , X 1 , ..., X p-1 ), that is Cycle left by p positions.

    Before throwing

    Claim:

    123456789 -> 456789123

    Or treat 123 as a whole

    =>321456789

    =>321987654

    =>456789123

    reverse(a,0,p-1,p);
    reverse(a,p,n-1,n-p);
    reverse(a,0,n-1,n);
    

    Later in advance

    Claim:

    123456789 -> 789123456

    Treat 123456 as a whole

    => 654321789

    =>654321987

    => 789123456

    reverse(a,0,n-p-1,n-p);
    reverse(a,n-p,n-1,p);
    reverse(a,0,n-1,n);
    
Published 22 original articles · praised 0 · visits 781

Guess you like

Origin blog.csdn.net/sjxgghg/article/details/105594813