"408" Linear List and Linked List

Table of contents

1. Linear table

1.1. Sequence table

1.1.1. Define the sequence table (static allocation)

1.1.2. Initialize InitList(&L) (static allocation)

1.1.3. Define the sequence table (dynamic allocation)

1.1.4. Initialize InitList(&L) (dynamic allocation)

1.1.5. Insert element ListInsert(&L, i, e) 

1.1.6. Delete elements ListDelete(&L, i, &e)

1.1.7. Find LocateElem(&L, i, e) by value

1.1.8. Testing

1.2. Singly linked list

1.2.1. Define linked list

1.2.2. Initialize the linked list

1.2.3. Head insertion method

1.2.4. Tail insertion method

1.2.5. Find nodes by serial number

1.2.6. Find nodes by value

1.2.7, insert elements

1.2.8, delete elements

1.3, double linked list

1.3.1. Type definition of double linked list

1.3.2, Insert operation of double linked list 

1.3.3, delete operation of double linked list


1. Linear table

Linear tables generally include the following functions:

Initialize the linear table : initialize a linear table to get a brand new linear table.

Get the element at the specified position : directly get the element at the specified position i of the linear table.

Get the position of the element : Get the position i of an element on the linear table.

Insert element : Insert an element at the specified position i.

Delete element : delete an element at the specified position i.

Get Length : Return the length of the linear table.

There are generally two structures of linear tables, one is sequential storage implementation, and the other is chain storage implementation.

1.1. Sequence table

1.1.1. Define the sequence table (static allocation)

#define Maxsize 50  //定义线性表最大长度
typedef int ElemType;  //定义元素类型
typedef struct {  //定义结构体
    ElemType data[Maxsize];  //定义顺序表的元素
    int length;  //定义线性表的长度
}SqList;

1.1.2. Initialize InitList(&L) (static allocation)

void InitList(SqList *L){
    L -> length = 10;
}

1.1.3. Define the sequence table (dynamic allocation)

typedef int ElemType;  //定义元素类型
typedef struct {  //定义结构体
    ElemType *data;  //定义顺序表的元素
    int length;  //定义线性表的长度
    int Maxsize;  //定义最大长度
}SqList;

1.1.4. Initialize InitList(&L) (dynamic allocation)

_Bool InitList(SqList *L){
    L->length = 10;
    L->data = malloc(sizeof (ElemType) * L->length);  //malloc函数手动申请一片空间
    if(L->data == NULL) return false;  // 如果申请的结果为NULL表示内存空间分配失败
    L->Maxsize = 0;  //默认长度0
    return true;
}

1.1.5. Insert element ListInsert(&L, i, e) 

//在位置i插入元素e
_Bool ListInsert(SqList *L, int i, ElemType e){
    
        if(i < 1 || i > L->length + 1) return false;  //判断i是否合法,小于1或者大于最大长度返回false
        if(L->length > L->Maxsize) return false;  //存储空间已满,不可插入
// j为顺序表的长度,将j向i靠近(j--)到达i的位置
        for (int j = L->length; j >= i; j--) {
        L->data[j] = L->data[j - 1];  //将j位置的元素后移一位,通过for不断循环直到到达i位置,此时候原数组中i位置空缺
}
        L->data[i - 1] = e;  //此时j在i的位置,由于顺序表从0开始,在i位置就是在L.data[j-1]插入
        L->length++;  //顺序表长度+1
        return true;
}

 1.1.6. Delete elements ListDelete(&L, i, &e)

//在第i个位置删除元素e
_Bool ListDelete(SqList *L, int i, ElemType *e){
    if(i < 1 || i > L->length + 1) return false;  //判断i是否合法,小于1或者大于最大长度返回false
    e = L->data[i - 1];  //将第i个位置的元素赋给e,此时顺序表中第i个位置空
    for (int j = i; j < L->length; j++) {
        L->data[j - 1] = L->data[j]; //循环,将第j个赋给第j-1个,也就是向前放
 }
        L->length--; //长度减1
        return true;
}

1.1.7. Find LocateElem(&L, i, e) by value

//按值查找
int LocateElem(SqList *L, ElemType e) {
    int i;
    for (i = 0; i < L->length; i++) {  //遍历顺序表
        if (L->data[i] == e) return i + 1;  //当L.data[i] == e时,返回该元素的位序,i是该元素的下标
    }
    return 0;
}

1.1.8. Testing

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef int ElemType;
//定义一个顺序表,动态存储
typedef struct {
    ElemType *data;
    int length,Maxsize;
}SqList;

//初始化一个顺序表
_Bool InitList(SqList *L){
    L->data = malloc(sizeof (ElemType) * L->length);
    if(L->data == NULL) return false;
    L->length = 0;  //初始化为0
    L->Maxsize = 50; // 定义最大长度
    return true;
}

//插入元素
//在i位置插入元素e
_Bool ListInsert (SqList *L, int i, ElemType e){
    if(i < 1 || i > L->length + 1) return false;
    if(i > L->Maxsize) return false;
    for (int j = L->length; j >= i; j--) {
        L->data[j] = L->data[j-1];
    }
    L->data[i-1] = e;
    L->length ++;
    return true;
}


//删除元素
_Bool ListDelete(SqList *L, int i, ElemType *e){
    if(i < 1 || i > L->length + 1) return false;
    if(i > L->Maxsize) return false;
    e = L->data[i-1];
    for (int j = i; j < L->length; j++) {
        L->data[j-1] = L->data[j];
    }
    L->length --;
    return true;
}

int ListSize(SqList *L){
    return L->length;
}

//按值查找
int LocateElem(SqList *L, ElemType e) {
    int i;
    for (i = 0; i < L->length; i++) {  //遍历顺序表
        if (L->data[i] == e) return i + 1;  //当L.data[i] == e时,返回该元素的位序,i是该元素的下标
    }
    return 0;
}


void printList(SqList *L){

    for (int i = 0; i < L->length; ++i) {
        printf("%d", L->data[i]);
    }
    printf("\n");
}


int main() {
    SqList L;
    InitList(&L);
    ListInsert(&L, 1, 6);
    printList(&L);
    ListInsert(&L, 2, 44);
    printList(&L);
    ListInsert(&L, 3, 444);
    printList(&L);
}

1.2. Singly linked list

        The linked list is different from the sequential list. The sequential list uses an array as a storage container and needs to allocate a continuous and complete memory space for use, while the linked list does not need it. It connects scattered nodes through a pointer to form a chain structure. It does not need to apply for continuous space, it only needs to be connected in order, and it is still logically adjacent.

1.2.1. Define linked list

typedef int ElemType;
typedef struct LNode{
    ElemType data; //数据域
    struct LNode * next;  //指向下一节点的指针
}LNode, *LinkList;

1.2.2. Initialize the linked list

void InitList(LNode *L){  //  将定义的结构体命名为L
    L->next = NULL;  // 链表L中的next指针指向NULL
}

1.2.3. Head insertion method

//头插法
LinkList List_HeadInsert(LinkList &L){
    LNode *s;  int x; //定义结点指针s,插入数据x
    L = (LinkList)malloc(sizeof (LNode));  //创建头结点,前面表示LinkList型的
    L->next = NULL;  //初始化链表,指针指向NULL
    scanf("%d", &x);   //输入结点的值,也就是数据域
    while (x!=9999) {  //输入9999时表示结束链表创建
        s = (LNode *) malloc(sizeof(LNode));  //创建一个新的,待插入的结点
        s->data = x;
        s->next = L->next;
        L->next = s;
        scanf("%d", &x);  //继续读取数据,读一次插一次
    }
     return L;  
    }

1.2.4. Tail insertion method

//尾插法
LinkList List_TailInsert(LinkList L){
    int x;  //数据域
    L = (LinkList) malloc(sizeof (LNode));  //为链表开创一段内存空间
    LNode *s, *r=L;  //定义两个指针,其中r是表尾指针,s是指向新结点的指针
    scanf("%d", &x);  //通过输入接受到数据x
    while (x!=9999) {
        s = (LNode *) malloc(sizeof(LNode));  //为待插入的结点赋予一段内存空间
        s->data = x;
        r->next = s;
        r = s;
        scanf("%d", &x);
    }
    r->next = NULL;  //表尾指针置空
    return L;
    }

1.2.5. Find nodes by serial number

//按序号查找节点,序号为i
_Bool GetElem(LinkList L, int i) {
    if (i < 1) return 0;  //当序号小于1时,此时不存在,返回0
    int j = 1; //计数
    LNode *p = L->next;  //第一个位置赋值给p
    while (p != NULL && j < i) {  //当j<i时继续遍历,当j=i时跳出遍历,当p不断后移后直到NULL,跳出循环
        p = p->next;  //当j<i时候p指向它的下一个节点
        j++; // 遍历一次j就+1
    }
    return p;
}

1.2.6. Find nodes by value

LNode *LocateElem(LinkList L, ElemType e){ //待查找的链表L 数据元素为e
    LNode *p = L->next; // p指向头结点
    while (p!=NULL && p->data != e)  // 当p为空或查找到p的数据域为e时跳出循环
        p = p->next;  // 没找到,向后指,p指向下一节点
    return p;
}

1.2.7, insert elements

P = GetElem(L, i-1);  //调用GetElem函数找到前驱节点
s -> next = p -> next;  // 结构同前面头插法
p -> next = s;

1.2.8, delete elements

p = GetElem(L, i-1); //调用GetElem函数获取待删除元素前一个位置
q = p -> next;  // q指针指向待删除结点
p -> next = q -> next;  // p指向q的后一个结点
free(q);  // 释放q结点

1.3, double linked list

1.3.1. Type definition of double linked list

typedef int ElemType;
//定义双链表的结点类型
typedef struct DNode{
    ElemType data;  //数据域
    struct DNode *prior, *next;  // 前驱结点的指针;后继结点的指针
}DNode, *DLinklist;

1.3.2, Insert operation of double linked list 

A picture is worth a thousand words

s -> next = p -> next;
p -> next -> prior = s;
s -> prior = p;
p -> next = s;

1.3.3, delete operation of double linked list

p->next = q->next;
q->next->prior=p;
free(q);

Guess you like

Origin blog.csdn.net/m0_60964321/article/details/129677551