【Data Structure Learning Record 3】——Single Linked List

1. Principle

1. Brief description

Because the sequence table is a fixed space, there will be some problems with the space time rate. If we can dynamically connect one node after another in some way, it might be much better. Therefore, in this case, we came up with the data structure of a singly linked list.

2. Analysis

For singly linked lists, we definitely still need 增删改查these basic functions. Further, in addition to the definition of a node, we store in addition to data, should be capable of further needs to include a "sense" the data structure of the next node, then we can use 指针instead.

3. Illustration of ideas

1.3.1 Definition of Node

Insert picture description here

We can create a structure that contains two parts: the first part is our data; the second part stores our pointer to the next node, and *nextinitializes it to the default value NULL. As long as it is detected later, it is not NULL. Then it shows that there are nodes behind him. Once a node is pointed NULL, it means that this node is over.

1.3.2 Definition of Linked List

Insert picture description here

Because the structure of our entire linked list is the same, we can directly take a fixed node as it 表头.
Then, according to habit, we specify the sequence number of the first node pointed to by the header 0.

1.3.3 Initialization of linked list/node

Because our linked list is composed of the same nodes, the initialization of our linked list is equal to the initialization of our nodes. So we only need to use to mallocgenerate a node and *nextpoint NULLit to it.

1.3.4 Table traversal

Table traversal we can use whileto carry out until *next == NULL.

1.3.5 Destruction of the table

For the destruction of the table, we can traverse, freeand until the end.

1.3.6 Node Insertion

Insert picture description here

We can find the previous position of the node to be inserted by traversing + counting , record it as LastNode, and perform the following operations:

  1. Creating good node information to be inserted, denoted ThisNode, and ThisNodethe *nextassignment to LastNodethe *next. In this way, the node we inserted will point to our next node.
  2. Will be LastNodethe *nextassigned ThisNodeaddress. In this way, the table is complete again.
    For example, in the figureLastNode 是 0 ThisNode = index 是 1

1.3.7 Deletion of nodes

Insert picture description here

Similar to inserting, we still have to traverse to the previous position of the node to be deleted, and then execute this process:

  1. Read and save LastNodethe *nextaddress, this is what we want to delete ThisNode.
  2. We put LastNodethe *nextpoint ThisNodeof *next. At this point, if we traverse the list again, it can no longer be traversed ThisNode, it is skipped
  3. freeOff ThisNodebecause it has no meaning. The deletion of such a node.

1.3.7 Modification of nodes

There is nothing to say about the modification, just modifying the data will not change the structure of the linked list, so just traverse the modification directly data.

1.3.8 Node query

For query, just traverse.

2. Code

Modify the main function yourself to achieve the effect

#include <stdio.h>
#include <stdlib.h>

#define OK      1
#define ERROR   0

// 定义数据类型
typedef struct elemType {
    
    
    int data1;
    int data2;
}data;

//定义节点
typedef struct Node {
    
    
    data data;
    struct Node *next;
    //不能写成 Node *next 因为此时还没有typedef成功,只能用结构体嵌套的方式定义
}Node;

Node* ListInit(void);
void ListShow(Node *list);
int ListInsert(Node *list, data data_in, int index);
int ListDelect(Node *list, int index);
int ListModify(Node *List, data data_in, int index);
int ListQuery(Node *list, data data_in);

int main()
{
    
    
    Node* List = ListInit();
    data test;
    test.data1 = 1;
    test.data2 = 2;

    ListInsert(List, test, 0);
    test.data1 = 3;
    ListInsert(List, test, 1);
    ListShow(List);
    printf("-------\n");
    //ListDelect(List, 0);
    //ListShow(List);
    //printf("-------\n");
    test.data1 = 5;
    ListModify(List,test,1);
    ListShow(List);
    printf("query get %d\n", ListQuery(List, test));
    test.data1 = 88;
    printf("query get %d\n", ListQuery(List, test));
    return 0;
}

Node* ListInit(void)
{
    
    
    Node* list = (Node *)malloc(sizeof(Node));  // 创建节点

    if (list == NULL)
    {
    
    
        exit(0);    // 节点创建失败,退出
    }
    else
    {
    
    
        list->next = NULL;  // 节点初始化成功,返回节点作为表头
        return list;    
    }
}

void ListShow(Node* list)
{
    
    
    int cont = 0;

    while(list->next != NULL)   // 遍历到表末尾
    {
    
    
        list = list->next;  // 跳过表头,list变成真第一个节点
        printf("No.%d data is %d %d\n", cont, list->data.data1, list->data.data2);
        ++cont; // 这个节点已输出,cont变成下一个节点的序号
    }

}

int ListInsert(Node *list, data data_in, int index)
{
    
    
    int cont = -1;  // 初始化为 -1,简化后面操作
    Node *ThisNode = (Node *)malloc(sizeof(Node));
    
    ThisNode->data = data_in;   // 初始化创建好的节点
    ThisNode->next = NULL;  

    if (list->next == NULL) //  判断这个表是不是空表,空表就特殊处理了
    {
    
    
        list->next = ThisNode;
        return OK;
    }

    while(list->next != NULL && cont < index - 1)   //遍历 到插入的前一个节点
    {
    
    
        list = list->next; //移动到下一个节点
        ++cont; // 因为list初值是表头,cont初值-1,所以这样操作后,这句话后的list的节点序号和cont对应
    }

    ThisNode->next = list->next;    //更新操作
    list->next = ThisNode;

    return OK;
}

int ListDelect(Node *list, int index)
{
    
    
    Node *dNode = NULL;     //声明一下要删除的节点变量
    int cont = -1;  //  同理

    if (list->next == NULL)
    {
    
    
        return ERROR;   //空链表,没意义,返回错误
    }
    else
    {
    
    
        while(list->next != NULL && cont < index - 1)
        {
    
    
            list = list->next;
            ++cont;
            // 和插入一样的解释,遍历。
        }

        dNode = list->next;
        list->next = dNode->next; //    这样就跳过了dNode
        free(dNode);    //释放掉删除的Node

        return OK;
    }
}

int ListModify(Node *list, data data_in, int index)
{
    
    
    int cont = -1;

    while(list->next != NULL && cont < index) // 因为要删除,所以要遍历到它本身
    {
    
    
        list = list->next;
        ++cont;
    }
    if (cont == index)  // 确定遍历到了它
    {
    
    
        list->data = data_in;
        return OK;
    }
    else    // 理论上来说是长度不够 index比表长更长
    {
    
    
        return ERROR;
    }
}

int ListQuery(Node *list, data data_ck)
{
    
    
    int cont = 0;
    
    while(list->next != NULL)   // 查询同修改
    {
    
    
        list = list->next;
        if (list->data.data1 == data_ck.data1 && list->data.data2 == data_ck.data2)
        {
    
    
            return cont;
        }
        ++cont;
    }
    return -1;
} 

Guess you like

Origin blog.csdn.net/u011017694/article/details/109287688