[Data structure learning] 2. Linked list and binary tree

foreword

Write a makefile and add asan to check memory related content. Make directly in this directory. Because I always can't control the application and release.

SRC = $(wildcard *.cpp)
OBJ = $(patsubst %.cpp, %.o, $(SRC))

ALL: test.out

test.out: $(OBJ)
    g++ -fsanitize=address $< -lm -o $@ -l pthread

$(OBJ): $(SRC)
    g++ -fsanitize=address -c $<  -lm -o $@ -l pthread

1 linked list

1.1 Concept

A linked list is a non-sequential and non-sequential storage structure on a physical storage unit , and the logical order of data elements is realized through the link order of pointers in the linked list . The linked list is composed of a series of nodes (each element in the linked list is called a node), and the nodes can be dynamically generated at runtime. Each node consists of two parts: one is a data field that stores data elements , and the other is a pointer field that stores the address of the next node.

------Baidu entry

I won’t introduce the concept of linked list, just look at the picture and practice.

From the above figure, we can know that there is no data in the head of the linked list, and the non-empty linked list directly points to the next node, and they are connected together in this way.

Define the structure of the node

struct Node
{
    int val;
    Node* next = nullptr;
};

The corresponding first node assignment and application

    // listNode* p1 = nullptr;
    // p1 = new listNode;
    Node* p1 = new Node; //上述两行等价与这一行
    p1->val = 2;
    p1->next = nullptr;

    Node* p2 = new Node;
    p2->val = 4;
    p2->next = nullptr;

Then connect the two nodes in series.

p1->next  = p2;

To see if the concatenation is successful, write a function to print the linked list. On my side, I also print out the head node for easy understanding.

void printList(Node* list)
{
    int i  = 0;
    while (list != nullptr)
    {
        cout << "[" << i  << "]:"<< list->val << " ";
        list = list->next;
        i++;
    }
    cout << endl;
}

print directly

printList(p1);

The output terminal result is: Indicates that the connection is successful. Note that the head node generally does not store data. But it is theoretically possible to store data.

[0]:2 [1]:4

1.2 Basic operation of LIST

  • tail plug

    The most commonly used insertion data in singly linked list is tail insertion.

    The working principle of tail insertion is to traverse to the nullptr at the end of the linked list and insert the corresponding node at this position

    Look directly at the code implementation. When inserting, pay attention to the judgment that it is null when list->next.

    void pushBack(Node* list,int val)
    {
        Node* cur = p;
        Node* newNode = new Node;
        newNode->val = val;
        while(cur->next!=nullptr)
        {
            cur = cur->next;
        }
        cur->next = newNode;
    }
    

    The test demo is

    int main()
    {
        Node* p1 = new Node;
        p1->val = 1;
    
        pushBack(p1,2);
        pushBack(p1,3);
        pushBack(p1,4);
        printList(p1);
    
        return 0;
    }
    

The result of the printout is

[0]:1 [1]:2 
[0]:1 [1]:2 [2]:3 
[0]:1 [1]:2 [2]:3 [3]:4 
[0]:1 [1]:2 [2]:3 [3]:4 
  • head insertion

    Head insertion, as the name implies, is to insert data at the head of the linked list, and insert the new node behind the head node.

void pushFront(Node* p,int val)
{

if(p == nullptr)
{
p = new Node;
p ->val = val;
p ->next = nullptr;
}
else
{
Node* newNode = new Node;
newNode->val = val;
newNode->next = p->next;
p->next = newNode;
}
}
  • Find the length of the linked list

The length of the linked list does not count the head node. The normal traversal counting from the beginning is enough.

int lensList(Node* p)
{
    int count = 0;
    while (p->next!=nullptr)
    {
        count++;
        p = p->next;
    }
    return count;
}
  • reverse order of linked list

void reverse(Node* head)
{
    if ((head->next == nullptr )||(head->next->next == nullptr))
    {
        return;
    }
    else
    {
        Node* pCur = head->next;
        Node* pNext = pCur->next;
        Node* pre = nullptr;
        while (pNext)
        {
            pCur->next = pre;
            pre = pCur;
            pCur = pNext;
            pNext = pCur->next;
        }
        pCur->next = pre;
        head->next = pCur;
        return;
    }
}
  • Delete the linked list: store a node as a temporary node, and then delete the temporary node continuously.

    void deleteList(Node* head)
    {
        while (head)
        {
            Node* del = head;
            head = head->next;
            delete del;
        }
        head = nullptr;
        delete head;
    }
    

2 second cutting tree

2.1 Concept

struct binaryTree
{
    int data;
    binaryTree* left;
    binaryTree* right;
};

Preorder traversal of the binary tree: first output the root node, then output the left child, and then output the right child

void preOrder(binaryTree* node)
{
    if(node)
    {
        cout << node->data << " ";
        preOrder(node->left);
        preOrder(node->right);
    }
}

Inorder traversal of a binary tree: output the left child first, then the root node, and then the right child.

void midOrder(binaryTree* node)
{
    if(node)
    {
        midOrder(node->left);
        cout << node->data << " ";
        midOrder(node->right);
    }
}

Post-order traversal of the binary tree: first output the left child, then output the right, and then output the root node

void postOrder(binaryTree* node)
{
    if(node)
    {
        postOrder(node->left);
        postOrder(node->right);
        cout << node->data << " ";
    }
}

Pre-order, in-order, and post-order traversals are determined according to the position of the root node.

Related demos are as follows

int main()
{
    binaryTree* t1 = new binaryTree;
    t1->data = 1;

    binaryTree* t2 = new binaryTree;
    t2->data = 2;

    binaryTree* t3 = new binaryTree;
    t3->data = 3;

    t1->left = t2;
    t1->right = t3;

    preOrder(t1);
    cout << endl;
    midOrder(t1);
    cout << endl;
    postOrder(t1);
    cout << endl;

}

Guess you like

Origin blog.csdn.net/qq_38753749/article/details/128720086