1. Second-level pointer (pointer to pointer)
So what is the second-level pointer used? Let's look at an example of a chain stack and a chain queue implemented using a second-level pointer.
Description of each file in the source code:
Definitions of nodes stored in the stack_queue.h file and function declaration
Stack. c file storage stack implementation
Queue storage in the queue. c file
Stack_queue.h file:
# Ifndef stack_queue_h # define stack_queue_h # include <stdlib. h> # define error-10000 typedef int nodetype; // set the node type to int type // stack, and define nodes in the queue as typedef struct node {nodetype data; struct node * Next;} node, * pnode; // The chain stack uses the single-chain table of the leading node to implement void init_stack (pnode * Top ); // initialize the stack nodetype POP (pnode * Top); // stack nodetype PEP (pnode top); // obtain the top element of the stack void push (pnode * Top, nodetype data ); // press the stack int stack_empty (pnode top); // determine whether the stack is empty. // use the cyclic single-chain table of the leading node in the chain queue to implement void init_queue (pnode * rear ); // initialize the queue nodetype de_queue (pnode * rear); // nodetype get_queue (pnode rear); // obtain the queue Header element void en_queue (pnode * rear, nodetype data ); // enter the queue int queue_empty (pnode rear); // determine whether the queue is empty # endif
Stack. c file:
# Ifndef stack_c # define stack_c # include "stack_queue.h" // initialize the stack and create a head node as the bottom element of the stack. Top is the top pointer void init_stack (pnode * Top) {pnode P; P = (pnode) malloc (sizeof (node); * Top = P; (* Top)-> next = NULL ;} // out-of-stack (to change the top pointer of the stack, the top pointer of the stack is moved down, so a second-level pointer is passed in) nodetype POP (pnode * Top) {nodetype data; pnode q = * Top; If (! Stack_empty (* Top) {DATA = Q-> data; * Top = (* Top)-> next; // change the stack top pointer Q-> next = NULL; free (Q); return data;} return error;} // view the top element of the stack (no modification is required for the stack, so no second-level pointer is required) nodetype PEP (pnode top) {If (! Stack_empty (top) {return top-> data;} return error;} // in the stack, move the top pointer of the stack up void push (pnode * Top, nodetype data) {pnode = (pnode) malloc (sizeof (node); pnode-> DATA = data; pnode-> next = * Top; (* Top) = pnode; // change the stack top pointer} // determine whether the stack is empty (no stack modification is required, so no second-level pointer is required) int stack_empty (pnode top) {If (top-> next = NULL) return 1; elsereturn 0 ;}# endif
Queue. c file:
# Ifndef queue_c # define queue_c # include "stack_queue.h" // initialize the queue (create a cyclic queue of the leading node) void init_queue (pnode * rear) {pnode P; P = (pnode) malloc (sizeof (node); P-> next = P; * rear = P;} // output queue (note that the tail pointer of the queue must be changed when there is only one element) nodetype de_queue (pnode * rear) {nodetype data; pnode; If (! Queue_empty (* rear) {pnode = (* rear)-> next; Data = pnode-> data; (* rear) -> next = pnode-> next; If (pnode = * rear) // only one knots except the header node * rear = (* rear) -> next; pnode-> next = NULL; free (pnode); return data;} else return error;} // obtain the nodetype get_queue (pnode rear) {If (! Queue_empty (rear) {return rear-> next-> data;} else return error;} // enter the queue (change the team tail pointer every time you enter the queue) void en_queue (pnode * rear, nodetype data) {pnode; pnode = (pnode) malloc (sizeof (node); pnode-> next = (* rear)-> next; pnode-> DATA = data; (* rear)-> next = pnode; * rear = pnode; // move the pointer to the end of the Team One by one} // determines whether it is null int queue_empty (pnode rear) {If (rear-> next = rear) return 1; elsereturn 0;} # endif
Test. c file (TEST ):
# Include "stack. C "# include" queue. C "# include <stdio. h> void main () {pnode stack; pnode queue; puts ("test chain Stack:"); init_stack (& stack); push (& stack, 1 ); push (& stack, 2); printf ("% d \ n", pop (& stack); printf ("% d \ n", pop (& stack )); puts ("test chain queue:"); init_queue (& Queue); en_queue (& queue, 1); en_queue (& queue, 2 ); printf ("% d \ n", de_queue (& Queue); printf ("% d \ n", de_queue (& Queue ));}
Summary: pointers are also passed through values. When we want to change the value of the first-level pointer in the function to be called, we need to take the second-level pointer as the parameter. This situation is often encountered. For example, when operating on a linked list (with no head node), the first element of the linked list is used to find the elements in all other linked lists, if the first element is deleted during the delete operation, you need to change the pointer of the linked list header. Of course, when a binary tree operation is performed on a root node, the first-level pointer must be changed.
2. Summary of pointer data types (coming from "C language programming" Tan haoqiang)