[The eleventh day of the C language inspector training camp] Three articles thoroughly understand the linear table in the data structure (2) ----- addition, deletion, modification, query and destruction of the linked list

foreword

Teacher Tan Haoqiang said: "The pointer is the soul of the C language." The linked list mentioned today is built by the soul of the C language. After learning the linked list, you can use the linked list to easily realize data structures such as trees and graphs, and easily resolve the data structure of the postgraduate entrance examination. Big question! Before talking about today's content, let's take a look at the big questions about linked lists that have appeared in previous years.
insert image description here

1. Linked list

Linked lists are usually suitable for the following situations

  • Insert and delete operations in a linear table with a large number of elements or very frequently
  • The size of the linear table is not easy to determine

1. Basic introduction

The picture below shows the storage method of the linked list in terms of logical structure and physical structure (the gray is the actual storage structure, and the blue ball is the logical structure)
insert image description here
记住最主要的一点:链表的每一个节点都由指针域与数据域组成,其中指针域负责记录下一个节点的地址,数据域负责记录本节点数据。一个指针域的节点可以串成单链表,两个指针域的节点可以串成双向、循环链表、二叉树等数据结构。做出改变的仅仅是指针域的关系!

The teacher said that there will be a class on data structure in April in the future, and it should be introduced in detail at that time. At present, it is only necessary to understand.
Some concepts in singly linked list are as follows:
insert image description here

2. The principle and practice of adding, deleting, modifying and checking

Inserting elements in the linked list Inserting elements
can be divided into head insertion method, tail insertion method, and middle insertion method. The following picture is the implementation principle, and the codes are head insertion method, tail insertion method, and middle insertion method.
insert image description here

//头插法
void head_insert(myList* head,ElemType e){
    
    
    myList *p= (myList*)malloc(sizeof (myList));
    p->data=e;
    p->next=head->next;
    head->next=p;
    // 如果写成以下样子,将不会有效果
    // head->next=p->next;
}
//尾插法
void tail_insert(myList* tail,ElemType e){
    
    
    myList *p;
    p=tail;
    while (p->next!=NULL){
    
    
        p=p->next;
    }
    p->next=(myList*) malloc(sizeof (myList));
    p->next->data=e;
    p->next->next=NULL;
}
//随机插入
bool random_insert(myList* head,int i,ElemType e){
    
    
    myList *p=head;
    int j=0;
    for(;p!=NULL,j<i-1;j++){
    
    
        p=p->next;
    }
    if(p!=NULL){
    
    
        myList *q=(myList*)malloc(sizeof (myList));
        q->data=e;
        q->next=p->next;
        p->next=q;
        return true;
    }else{
    
    
        return false;
    }
}

Delete nodes in the linked list
To delete nodes in the linked list, the most important thing is to change the pointer relationship of the nodes reasonably.

insert image description here

insert image description here
code:

//删除相应元素
bool delete_e(myList* head,ElemType e){
    
    
    for (myList* p=head;p->next!=NULL;p=p->next){
    
    
        if(p->next->data==e){
    
    
            myList *q =p->next;
            p->next=p->next->next;
            free(q);
        }
    }
    return false;
}

Find a node in a linked list

Finding nodes can generally be divided into:

  • search by serial number
    insert image description here
  • lookup by value
    insert image description here

I implemented search by value and search by serial number separately. Search by value only judges whether it is found or not. Search by serial number returns the found information, and returns NULL if there is no match.

//按位置查找
myList* index_search(myList *head,int i){
    
    
    if(i<=0){
    
    
        return NULL;
    }
    myList *p=head;
    int j=0;
    // 循环终止条件如果有多个的话需要用逻辑表达式连接
    // 不可以使用逗号连接,用逗号连接遵循逗号表达式使用规则
    for(;p->next!=NULL&&j<i-1;j++){
    
    
        p=p->next;
    }
    return p->next;
}
//按值查找
bool element_search(myList *head,ElemType e){
    
    
    for (myList* p=head;p->next!=NULL;p=p->next){
    
    
        if(p->next->data==e){
    
    
            return true;
        }
    }
    return false;
}

Generally speaking, it is more useful to search by value!

Destroy the linked list
This is also a commonly used function, it is relatively simple so I won’t go into details! Just leave a message in the comment area if you don't understand the code.

//销毁链表
void destroy_myList(myList* head){
    
    
    myList *p=head->next;
    myList *q=NULL;
    while (p!=NULL){
    
    
        q=p;
        p=p->next;
        free(q);
    }
    head->next=NULL;
}

Here are two functions for traversing linked lists

//遍历链表
void print_list(myList *head){
    
    
    if(head->next==NULL){
    
    
        printf("null!!!");
    }
    for (myList *p=head;p->next!=NULL;p=p->next){
    
    
        printf("%2c",p->next->data);
    }
    printf("\n");
}
void print(myList *p){
    
    
    if(p!=NULL){
    
    
        printf("%2c\n",p->data);
    }else{
    
    
        printf("null\n");
    }
}

Summary and source code

Advantages and disadvantages of linked lists
insert image description here
Regarding linked list debugging, since linked lists do not exist continuously in memory, the virtual memory view of the compiler is not useful when debugging. You can use the following methods for debugging; through single-step debugging, Directly in the variable window, click the head pointer L one by one to observe whether each node meets your expectations. At the same time, when you are practicing, don't enter too much data, the amount of data is less than or equal to the class.

insert image description here

Source code
This code realizes the addition, deletion and checking of the linked list (it is relatively simple to modify and check for duplicates, you can add it down), and each function function is directly above the function. Interested students can study it by themselves. Welcome to leave a message in the comment area!

//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include<stdlib.h>
#define bool int
#define true 1
#define false 0
typedef char ElemType;
//数组类型
struct myList{
    
    
    ElemType data;
    struct myList* next;
};
typedef struct myList myList;
//头插法
void head_insert(myList* head,ElemType e){
    
    
    myList *p= (myList*)malloc(sizeof (myList));
    p->data=e;
    p->next=head->next;
    head->next=p;
    // 如果写成以下样子,将不会有效果
    // head->next=p->next;
}
//尾插法
void tail_insert(myList* tail,ElemType e){
    
    
    myList *p;
    p=tail;
    while (p->next!=NULL){
    
    
        p=p->next;
    }
    p->next=(myList*) malloc(sizeof (myList));
    p->next->data=e;
    p->next->next=NULL;
}
//随机插入
bool random_insert(myList* head,int i,ElemType e){
    
    
    myList *p=head;
    int j=0;
    for(;p!=NULL,j<i-1;j++){
    
    
        p=p->next;
    }
    if(p!=NULL){
    
    
        myList *q=(myList*)malloc(sizeof (myList));
        q->data=e;
        q->next=p->next;
        p->next=q;
        return true;
    }else{
    
    
        return false;
    }
}
//按位置查找
myList* index_search(myList *head,int i){
    
    
    if(i<=0){
    
    
        return NULL;
    }
    myList *p=head;
    int j=0;
    // 循环终止条件如果有多个的话需要用逻辑表达式连接
    // 不可以使用逗号连接,用逗号连接遵循逗号表达式使用规则
    for(;p->next!=NULL&&j<i-1;j++){
    
    
        p=p->next;
    }
    return p->next;
}
//按值查找
bool element_search(myList *head,ElemType e){
    
    
    for (myList* p=head;p->next!=NULL;p=p->next){
    
    
        if(p->next->data==e){
    
    
            return true;
        }
    }
    return false;
}

//删除相应元素
bool delete_e(myList* head,ElemType e){
    
    
    for (myList* p=head;p->next!=NULL;p=p->next){
    
    
        if(p->next->data==e){
    
    
            myList *q =p->next;
            p->next=p->next->next;
            free(q);
        }
    }
    return false;
}
//销毁链表
void destroy_myList(myList* head){
    
    
    myList *p=head->next;
    myList *q=NULL;
    while (p!=NULL){
    
    
        q=p;
        p=p->next;
        free(q);
    }
    head->next=NULL;
}
//遍历链表
void print_list(myList *head){
    
    
    if(head->next==NULL){
    
    
        printf("null!!!");
    }
    for (myList *p=head;p->next!=NULL;p=p->next){
    
    
        printf("%2c",p->next->data);
    }
    printf("\n");
}
void print(myList *p){
    
    
    if(p!=NULL){
    
    
        printf("%2c\n",p->data);
    }else{
    
    
        printf("null\n");
    }
}
int main() {
    
    
    // 创建一个头结点(头结点一般不用于存储信息)
    myList *head=(myList*)malloc(sizeof (myList));
    head->next=NULL;
    printf("tail insert some data!\n");
    tail_insert(head,'h');
    tail_insert(head,'o');
    tail_insert(head,'w');
    tail_insert(head,'a');
    tail_insert(head,'r');
    tail_insert(head,'e');
    tail_insert(head,'y');
    tail_insert(head,'o');
    tail_insert(head,'u');
    print_list(head);
    printf("after head_insert:");
    head_insert(head,'q');
    head_insert(head,'q');
    print_list(head);
    printf("after random_insert:");
    random_insert(head,3,'t');
    print_list(head);
    delete_e(head,'t');
    printf("after delete:");
    print_list(head);
    printf("search:%c \nsearch_reasult:%d\n", 'q',element_search(head,'q'));
    myList *q= index_search(head,10);
    print(q);
    q= index_search(head,1);
    print(q);
    q= index_search(head,100);
    print(q);
    q= index_search(head,-100);
    print(q);
    printf("list destroyed!!\n");
    destroy_myList(head);
    print_list(head);
    return 0;
}

警示自己:循环里面的循环变量变动可以使用,隔开,但是循环终止条件必须使用逻辑运算符隔开!!!


insert image description here

Guess you like

Origin blog.csdn.net/apple_51931783/article/details/129051382