数据结构——链表

链表的初始化

如每个变量有个名称,链表也应该有个名称(代指),每个链表都需要有个头结点去指代该链表,因此链表初始化需要将头结点给定义出来(phead),还有要将临时插入的结点,也就是pnew给定义出来,一定要注意将指针初始化为NULL,不然会变成野指针

 STU *head = NULL, *pnew = NULL;

链表的增(分为头插法 尾插法,头插法后续更新)

前言

笔者学习时有个很严重的错误 就是在插入链表 创建新的节点后 总喜欢把创造完的结点给删除 实际上这个结点不应该删除,就应该让他站内存 删了数据就没了

尾插法

首先判断该链表是否为空链表(没有结点,头结点指向空),如果是空链表,那么pnew作为它的头,如果不是空链表,那么通过头结点遍历到尾结点,再让尾结点插入pnew(新的节点)

void insert_by_tail(STU **head, STU *pnew)
{
    STU *pmove = *head;
    if (*head == NULL)
    {
        *head = pnew;
        pnew->next = NULL;
    }
    else
    {
        while (pmove->next)
        {
            pmove = pmove->next;
        }
        pmove->next = pnew;
        pnew->next = NULL;
    }
    pnew = NULL;
}

头插法

pnew指向头部,然后头部指针更换为pnew。

void add_by_head(STU **head, STU *pnew)
{
    if (*head == NULL)
    {
        *head = pnew;
        pnew->next = NULL;
    }
    else
    {
        pnew->next = *head;
        *head = pnew;
    }
}

按照任意性质插法

用两个指针,一个指针指向满足某一性质节点的后结点,另一个在满足该性质节点的前结点,然后插入,不过要分情况,分满足该性质的结点是否为头结点或者尾结点。

void Add_by_anywhere(L **head, L *pnew)
{
    L *pf, *pb;
    pf = *head, pb = *head;
    if (*head == NULL || pnew->elem < (*head)->elem)
    {
        pnew->next = *head;
        *head = pnew;
        return;
    }
    while (pb != NULL && pb->elem <= pnew->elem)
    {
        pf = pb;
        pb = pb->next;
    }
    pf->next = pnew;
    pnew->next = pb;
    pb = NULL, pf = NULL;
    return;
}

链表的查

void prt_linkedlist(STU *head)
{
    STU *pmove = head;
    while (pmove != NULL)
    {
        cout << pmove->num << pmove->score << pmove->name << endl;
        pmove = pmove->next;
    }
}

查单一链表只需要知道其头结点,知道头结点后就直接用pmove遍历头结点直到尾结点

链表删

删除单节点

删除单节点需要用指针pb(前指针),pf(后指针)来找到删除节点的前坐标和当前坐标,让前坐标指向当前坐标的next指针,再free(pf)。

void DeleteNum(STU **head, int num) // 删除某一个元素
{
    if (*head == NULL)
    {
        cout << "None" << endl;
        return;
    }
    STU *pb, *pf;
    pb = *head, pf = *head;
    while (pb->num != num && pb->next != NULL)
    {
        pf = pb;
        pb = pb->next;
    }
    if (pb->num == num)
    {
        if (pb == *head)
        {
            *head = pb->next;
        }
        else
        {
            pf->next = pb->next;
        }
        free(pf);
    }
    else
    {
        cout << "none" << endl;
    }
}

删除链表

删除链表就是需要遍历一遍链表,遍历到哪删到哪,用两个指针,一个指针在移动(头指针),一个指针指向移动的指针(pmove),该指针在移动指针(头指针)移动后删当前节点。

void DeleteList(STU **head) // 删除所有链表
{
    STU *pmove = *head;
    while (*head)
    {
        pmove = *head;
        *head = (*head)->next;
        free(pmove);
        pmove = NULL;
    }
}

链表的改

遍历链表找到哪个节点就停下来 改数据

void ChangeNum(STU **head, int num, int k)
{
    STU *pmove = *head;
    while (pmove->num != num)
    {
        pmove = pmove->next;
    }
    pmove->score = k;
    return;
}

链表合并(递归)

注意事项1 创建新节点的时候指向new,注意事项2 head->next=merge(p1,p2) 注意事项3 如果要合并成非重合元素的链表 那么需要判断元素是否相等然后再进行移位, 移位后一定要判断链表是否为空 不然会segmantation default

L *merge(L *head1, L *head2)
{
    if (head1 == NULL)
        return head2;
    else
        return head1;
    L *head = NULL;
    if (head1->data == head2->data)
        head1 = head1->next;
    if (head1 == NULL)
        return head2;
    if (head1->data > head2->data)
    {
        head = head2;
        head2 = head2->next;
    }
    else
    {
        head = head1;
        head1 = head1->next;
    }
    head->next = merge(head1, head2);
    return head;
}

单链表的代码

全部代码

#include <iostream>
#define Elemtype int
using namespace std;
typedef struct List
{
    Elemtype elem;
    struct List *next;
} L;
void DeleteList(STU **head) // 删除所有链表
{
    STU *pmove = *head;
    while (*head)
    {
        pmove = *head;
        *head = (*head)->next;
        free(pmove);
        pmove = NULL;
    }
}
void add_by_tail(L **head, L *pnew)
{
    L *pmove = *head;
    if (*head == NULL)
    {
        *head = pnew;
        pnew->next = NULL;
    }
    else
    {
        while (pmove->next != NULL)
        {
            pmove = pmove->next;
        }
        pmove->next = pnew;
        pnew->next = NULL;
        pnew = NULL;
    }
}
void add_by_head(L **head, L *pnew)
{
    if (*head == NULL)
    {
        *head = pnew;
        pnew->next = NULL;
    }
    else
    {
        pnew->next = *head;
        *head = pnew;
    }
}
void delete_by_Elem(L **head, Elemtype x) // 删头结点的时候一定要注意!!!!
{
    L *pf, *pb;
    pf = *head, pb = *head;
    while (pb && pb->elem != x)
    {
        pf = pb;
        pb = pb->next;
    }
    if (pb == NULL)
    {
        cout << "None Delete" << endl;
    }
    else
    {
        if (pb == *head)
        {
            *head = pb->next;
            free(pb);
            pb = NULL;
            pf = NULL;
        }
        else
        {
            pf->next = pb->next;
            free(pb);
            pf = NULL;
            pb = NULL;
        }
    }
}
void PrtList(L **head)
{
    L *pmove = *head;
    cout << endl
         << "----Print----" << endl;
    while (pmove)
    {
        cout << pmove->elem << " ";
        pmove = pmove->next;
    }
    cout << endl;
}
void ChangeList(L **head, Elemtype a, Elemtype b)
{
    L *pmove = *head;
    while (pmove && pmove->elem != a)
    {
        pmove = pmove->next;
    }
    if (pmove == NULL)
    {
        cout << "None Change" << endl;
    }
    else
    {
        pmove->elem = b;
    }
}
void Add_by_anywhere(L **head, L *pnew)
{
    L *pf, *pb;
    pf = *head, pb = *head;
    if (*head == NULL || pnew->elem < (*head)->elem)
    {
        pnew->next = *head;
        *head = pnew;
        return;
    }
    while (pb != NULL && pb->elem <= pnew->elem)
    {
        pf = pb;
        pb = pb->next;
    }
    pf->next = pnew;
    pnew->next = pb;
    pb = NULL, pf = NULL;
    return;
}
int main()
{
    int n;
    cout << "amount of LinkeList" << endl;
    // n = 5;
    List *head = NULL, *pnew = NULL;
    cin >> n;
    while (n--)
    {
        pnew = (L *)malloc(sizeof(L));
        cin >> pnew->elem;
        Add_by_anywhere(&head, pnew);
    }
    PrtList(&head);
    delete_by_Elem(&head, 3);
    PrtList(&head);
    ChangeList(&head, 2, 5);
    PrtList(&head);
}

双向链表

头插法

头插法的思路是将pnew->next=head,pnew->prev=NULL,再把头节点更新为pnew

void insertAtBeginning(struct DoubleLinkedList *list, int value)
{
    struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
    newNode->data = value;
    newNode->next = list->head;
    newNode->prev = NULL;
    if (list->head != NULL)
    {
        list->head->prev = newNode;
    }
    list->head = newNode; // 插到前面
}

尾插法

思路是先遍历到尾部,让pnew->next=NULL,pnew->prev=pmove,pmove->next=pnew

void insertAtEnd(struct DoubleLinkedList *list, int value)
{
    struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
    newNode->data = value;
    newNode->next = NULL;
    if (list->head == NULL)
    {
        newNode->prev = NULL;
        list->head = newNode;
        return;
    }
    struct Node *current = list->head;
    while (current->next != NULL)
    {
        current = current->next;
    }
    current->next = newNode;
    newNode->prev = current;
}

思路是遍历到要删的结点 结点前的结点指向结点后结点,结点后的结点指向结点前的结点

void deleteNode(struct DoubleLinkedList *list, int value)
{
    struct Node *current = list->head;
    while (current != NULL && current->data != value)
    {
        current = current->next;
    }
    if (current == NULL)
    {
        printf("Node with value %d not found.\n", value);
        return;
    }
    current->next->prev = current->prev;
    current->prev->next = current->next;
    free(current);
    printf("Node with value %d deleted.\n", value);
}

思路是遍历到要改的数据,替换一下即可

void update(struct DoubleLinkedList *list, int old, int newd)
{
    struct Node *current = list->head;
    while (current != NULL && current->data != old)
    {
        current = current->next;
    }
    if (current == NULL)
    {
        printf("Node with value %d not found.\n", old);
        return;
    }
    current->data = newd;
    printf("Node value updated from %d to %d.\n", old, newd);
}

排序

思路和单链表排序一样,采用冒泡排序,快速排序和归并排序后面随缘更

void sort(struct DoubleLinkedList *list)
{
    if (list->head == NULL || list->head->next == NULL)
    {
        return;
    }
    struct Node *pf = list->head;
    struct Node *pb = NULL;
    bool isChange = true;
    while (isChange && pb != list->head)
    {
        isChange = false;
        for (pf = list->head; pf->next != pb; pf = pf->next)
        {
            if (pf->data > pf->next->data)
            {
                swap(pf->data, pf->next->data);
                isChange = true;
            }
        }
        pb = pf;
    }
}

循环链表的代码

#include <iostream>
#include <algorithm>
using namespace std;
struct Node
{
    int data;
    struct Node *next;
    struct Node *prev;
};
struct DoubleLinkedList
{
    struct Node *head;
};
void initList(struct DoubleLinkedList *list)
{
    list->head = NULL;
}
// 头插法
void insertAtBeginning(struct DoubleLinkedList *list, int value)
{
    struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
    newNode->data = value;
    newNode->next = list->head;
    newNode->prev = NULL;
    if (list->head != NULL)
    {
        list->head->prev = newNode;
    }
    list->head = newNode; // 插到前面
}
void insertAtEnd(struct DoubleLinkedList *list, int value)
{
    struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
    newNode->data = value;
    newNode->next = NULL;
    if (list->head == NULL)
    {
        newNode->prev = NULL;
        list->head = newNode;
        return;
    }
    struct Node *current = list->head;
    while (current->next != NULL)
    {
        current = current->next;
    }
    current->next = newNode;
    newNode->prev = current;
}
// 打印链表
void display(struct DoubleLinkedList *list)
{
    struct Node *current = list->head;
    while (current != NULL)
    {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}
void deleteNode(struct DoubleLinkedList *list, int value)
{
    struct Node *current = list->head;
    while (current != NULL && current->data != value)
    {
        current = current->next;
    }
    if (current == NULL)
    {
        printf("Node with value %d not found.\n", value);
        return;
    }
    current->next->prev = current->prev;
    current->prev->next = current->next;
    free(current);
    printf("Node with value %d deleted.\n", value);
}
void update(struct DoubleLinkedList *list, int old, int newd)
{
    struct Node *current = list->head;
    while (current != NULL && current->data != old)
    {
        current = current->next;
    }
    if (current == NULL)
    {
        printf("Node with value %d not found.\n", old);
        return;
    }
    current->data = newd;
    printf("Node value updated from %d to %d.\n", old, newd);
}
void search(struct DoubleLinkedList *list, int value)
{
    struct Node *current = list->head;
    while (current != NULL && current->data != value)
    {
        current = current->next;
    }
    if (current == NULL)
    {
        printf("Node with value %d not found.\n", value);
    }
    else
    {
        printf("Node with value %d found.\n", value);
    }
}
void sort(struct DoubleLinkedList *list)
{
    if (list->head == NULL || list->head->next == NULL)
    {
        return;
    }
    struct Node *pf = list->head;
    struct Node *pb = NULL;
    bool isChange = true;
    while (isChange && pb != list->head)
    {
        isChange = false;
        for (pf = list->head; pf->next != pb; pf = pf->next)
        {
            if (pf->data > pf->next->data)
            {
                swap(pf->data, pf->next->data);
                isChange = true;
            }
        }
        pb = pf;
    }
}
int main()
{
    struct DoubleLinkedList list;
    initList(&list);

    // 插入元素
    insertAtBeginning(&list, 3);
    insertAtBeginning(&list, 2);
    insertAtEnd(&list, 5);
    insertAtEnd(&list, 6);
    insertAtEnd(&list, 1);
    insertAtEnd(&list, 4);

    printf("Original List: ");
    display(&list);

    // 删除节点
    deleteNode(&list, 5);
    printf("List after deletion: ");
    display(&list);

    // 修改节点值
    update(&list, 2, 8);
    printf("List after update: ");
    display(&list);

    // 查找节点
    search(&list, 8);
    search(&list, 10);

    // 排序链表
    sort(&list);
    printf("Sorted List: ");
    display(&list);

    return 0;
}

循环链表

循环链表增

采用尾插法,切记将循环链表初始化为NULL

void append(CircularLinkedList *list, int data)
{
    Node *newNode = addNode(data);
    if (list->head == NULL)
    {
        list->head = newNode;
        newNode->next = list->head;
    }
    else
    {
        Node *pmove = list->head;
        while (pmove->next != list->head)
        {
            pmove = pmove->next;
        }
        pmove->next = newNode;
        newNode->next = list->head;
    }
}

循环链表查

遍历打印的时候用do while循环 保证循环链表正常进入 打出

void printList(CircularLinkedList *list)
{
    Node *pmove = list->head;
    do
    {
        cout << pmove->data << " ";
        pmove = pmove->next;
    } while (pmove != list->head);
    cout << endl;
}

代码

#include <iostream>
using namespace std;
typedef struct Node
{
    int data;
    struct Node *next;
} Node;
typedef struct
{
    Node *head;
} CircularLinkedList;
Node *addNode(int data)
{
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}
void append(CircularLinkedList *list, int data)
{
    Node *newNode = addNode(data);
    if (list->head == NULL)
    {
        list->head = newNode;
        newNode->next = list->head;
    }
    else
    {
        Node *pmove = list->head;
        while (pmove->next != list->head)
        {
            pmove = pmove->next;
        }
        pmove->next = newNode;
        newNode->next = list->head;
    }
}
void printList(CircularLinkedList *list)
{
    Node *pmove = list->head;
    do
    {
        cout << pmove->data << " ";
        pmove = pmove->next;
    } while (pmove != list->head);
    cout << endl;
}
int main()
{
    int x = 5;
    CircularLinkedList list;
    list.head = NULL;
    while (x--)
    {
        append(&list, x);
    }
    printList(&list);
}

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值