美文网首页数据结构
双向链表(含循环双链表)

双向链表(含循环双链表)

作者: 往sir_b2a2 | 来源:发表于2020-07-17 11:40 被阅读0次

    双向链表
    拓展1:前一节点的next可以看成是下一节点,某节点的pre可以看成是上一节点(偶尔会把next和pre看成一条线)
    先讲头插法,图片解释


    image.png

    尾插法,图片解释


    image.png
    插入操作,图片解释
    image.png

    删除操作,图片解释


    image.png

    无头节点版双链表:

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <stdlib.h>
    using namespace std;
    typedef struct node
    {
        int data;
        struct node* pre;
        struct node* next;
    }Node, * Link;
    Link create()
    {
        Link head = (Link)malloc(sizeof(Node));
        head->pre = NULL;
        head->next = NULL;
        return head;
    }
    void headadd(Link head, int newdata)
    {
        Link s = (Link)malloc(sizeof(Node));
        s->data = newdata;
        s->next = head->next;
        s->pre = head;
        if (head->next == NULL)
        {
            head->next = s;
        }
        else
        {
            head->next->pre = s;
            head->next = s;
        }
    }
    void tailadd(Link head, int newdata)
    {
        Link s = (Link)malloc(sizeof(Node));
        Link r = head;
        while (r->next)
        {
            r = r->next;
        }
        s->data = newdata;
        s->next = NULL;
        s->pre = r;
        r->next = s;
        r = s;
    }
    void insert(Link head,int i, int data)//i从head->next开始,i>=1
    {
        Link s = (Link)malloc(sizeof(Node));
        Link p = head;
        s->data = data;
        for (int j = 1; j < i; j++)//找到插入位置i的前一个位置
        {
            p = p->next;
        }
        s->next = p->next;
        s->pre = p;
        p->next = s;
    }
    void del(Link head,int i)
    {
        Link p = head;
        int j = 0;
        for (int j = 1; j < i; j++)//找到删除位置i的前一个位置
        {
            p = p->next;
        }
        if (p->next->next == NULL)
        {
            free(p->next);//与下面两句不要弄错顺序,因为弄错顺序的意思不一样,如果先指空的话,程序还是没有释放掉该节点空间
            p->next = NULL;
        }
        else
        {
            Link q = p->next;
            q->next->pre = p;
            p->next = q->next;
            free(q);
        }
    }
    void print(Link head)//打印和单链表一样,其实打印也就是比遍历多出一个cout那句
    {
        Link p = head->next;
        while (p)
        {
            cout << p->data << " ";
            p = p->next;
        }
    }
    void destroy(Link head)//销毁和单链表一样
    {
        Link p = head;
        Link q;
        while (p)
        {
            q = p->next;//先保留下一点的地址
            free(p);
            p = q;//此时p已经移动到q的位置,有点像继承遗产
        }
    }
    int main()
    {
        Link head = create();
        int n0;//链表有值点个数
        printf("输入链表所需的有效长度:");
        scanf("%d", &n0);
        for (int i = 0; i < n0; i++)
        {
            tailadd(head, 2*i);
        }
        cout << "初始时链表为这样:";
        print(head);
        cout << endl;
    
        int n1;
        printf("要插入的位置n1为(有值点下标从1开始):");
        scanf("%d", &n1);
        printf("要插入的元素n2为:");
        int n2;
        scanf("%d", &n2);
        insert(head, n1, n2);
        cout << "插入后链表为这样:";
        print(head);
        cout << endl;
    
        int n3;
        printf("要删除的位置n3(有值点下标从1开始):");
        scanf("%d", &n3);
        cout << "删除后链表为这样:";
        del(head,n3);
        print(head);
    
        destroy(head);
        return 0;
    }
    
    

    有头节点版双链表,就是Link create()多了个L,大部分功能函数的head改为了L

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <stdlib.h>
    using namespace std;
    typedef struct node
    {
        int data;
        struct node* pre;
        struct node* next;
    }Node, * Link;
    Link create()
    {
        Link head = (Link)malloc(sizeof(Node));
        Link L = (Link)malloc(sizeof(Node));
        head->next = L;
        L->pre = head;
        L->next = NULL;
        return head;
    }
    void headadd(Link L, int newdata)
    {
        Link s = (Link)malloc(sizeof(Node));
        s->data = newdata;
        s->next = L->next;
        s->pre = L;
        if (L->next == NULL)
        {
            L->next = s;
        }
        else
        {
            L->next->pre = s;
            L->next = s;
        }
    }
    void tailadd(Link L, int newdata)
    {
        Link s = (Link)malloc(sizeof(Node));
        Link r = L;
        while (r->next)
        {
            r = r->next;
        }
        s->data = newdata;
        s->next = NULL;
        s->pre = r;
        r->next = s;
        r = s;
    }
    void insert(Link head, int i, int data)//i从head->next开始,i>=1
    {
        Link s = (Link)malloc(sizeof(Node));
        Link p = head;
        s->data = data;
        for (int j = 1; j < i; j++)//找到插入位置i的前一个位置
        {
            p = p->next;
        }
        s->next = p->next;
        s->pre = p;
        p->next = s;
    }
    void del(Link L, int i)
    {
        Link p = L;
        int j = 0;
        for (int j = 1; j < i; j++)//找到删除位置i的前一个位置
        {
            p = p->next;
        }
        if (p->next->next == NULL)
        {
            free(p->next);//与下面两句不要弄错顺序,因为弄错顺序的意思不一样,如果先指空的话,程序还是没有释放掉该节点空间
            p->next = NULL;
        }
        else
        {
            Link q = p->next;
            q->next->pre = p;
            p->next = q->next;
            free(q);
        }
    }
    void print(Link L)//打印和单链表一样,其实打印也就是比遍历多出一个cout那句
    {
        Link p = L->next;
        while (p)
        {
            cout << p->data << " ";
            p = p->next;
        }
    }
    void destroy(Link head)//销毁和单链表一样
    {
        Link p = head;
        Link q;
        while (p)
        {
            q = p->next;//先保留下一点的地址
            free(p);
            p = q;//此时p已经移动到q的位置,有点像继承遗产
        }
    }
    int main()
    {
        Link head = create();
        int n0;//链表有值点个数
        printf("输入链表所需的有效长度:");
        scanf("%d", &n0);
        for (int i = 0; i < n0; i++)
        {
            tailadd(head->next, 2 * i);
        }
        cout << "初始时链表为这样:";
        print(head->next);
        cout << endl;
    
        int n1;
        printf("要插入的位置n1为(有值点下标从1开始):");
        scanf("%d", &n1);
        printf("要插入的元素n2为:");
        int n2;
        scanf("%d", &n2);
        insert(head->next, n1, n2);
        cout << "插入后链表为这样:";
        print(head->next);
        cout << endl;
    
        int n3;
        printf("要删除的位置n3(有值点下标从1开始):");
        scanf("%d", &n3);
        cout << "删除后链表为这样:";
        del(head->next, n3);
        print(head->next);
    
        destroy(head->next);
        return 0;
    }
    

    循环双链表

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <stdlib.h>
    using namespace std;
    typedef struct node
    {
        int data;
        struct node* pre;
        struct node* next;
    }Node, * Link;
    Link create()
    {
        Link head = (Link)malloc(sizeof(Node));
        head->pre = head;
        head->next = head;
        return head;
    }
    void tailadd(Link head)
    {
        Link r = head;
        int flag = 1;
        int c;
        while (flag)
        {
            cin >> c;
            if (c != -99999)
            {
                Link s = (Link)malloc(sizeof(Node));
                s->data = c;
                s->next = head;
                s->pre = r;
                r->next = s;
                r = s;
            }
            else
            {
                flag = 0;
            }
        }
    }
    void headadd(Link head)
    {
        int flag = 1;
        int c;
        while (flag)
        {
            cin >> c;
            if (c != -99999)
            {
                Link s = (Link)malloc(sizeof(Node));
                s->data = c;
                s->next = head->next;
                s->pre = head;
                if (head->next == NULL)
                {
                    head->next = s;
                }
                else
                {
                    head->next->pre = s;
                    head->next = s;
                }
            }
            else
            {
                flag = 0;
            }
        }
    }
    void insert(Link head, int i, int data)//i从head->next开始,i>=1(同普通双链表)
    {
        Link s = (Link)malloc(sizeof(Node));
        Link p = head;
        s->data = data;
        for (int j = 1; j < i; j++)//找到插入位置i的前一个位置
        {
            p = p->next;
        }
        s->next = p->next;
        s->pre = p;
        p->next = s;
    }
    void del(Link head, int i)
    {
        Link p = head;
        int j = 0;
        for (int j = 1; j < i; j++)//找到删除位置i的前一个位置
        {
            p = p->next;
        }
        Link q = p->next;
        q->next->pre = p;
        p->next = q->next;
        free(q);
    }
    void print(Link head)//打印和单链表一样,其实打印也就是比遍历多出一个cout那句
    {
        Link p = head->next;
        while (p!=head)
        {
            cout << p->data << " ";
            p = p->next;
        }
    }
    void destroy(Link head)//销毁和单链表有点不一样
    {
        Link p = head->next;
        Link q;
        while (p!=head)
        {
            q = p->next;//先保留下一点的地址
            free(p);
            p = q;//此时p已经移动到q的位置,有点像继承遗产
        }
        free(head);
    }
    int main()
    {
        cout << "开始初始化..............................................." << endl;
        Link head = create();
        cout << "初始化操作完毕!" << endl;
        cout << "开始建表,请输入元素:(这里是尾插法建表,输入-99999结束建表)..........." << endl;
        tailadd(head);
        cout << "建表操作完毕!" << endl;
        cout << "打印线性表中的所有数据:";
        print(head);
        cout << "-------------------------------------------------" << endl;
        cout << "开始插入(在第6个位置插入81)............................" << endl;
        insert(head, 6, 81);
        cout << "插入操作完毕!" << endl;
        cout << "打印线性表中的所有数据:";
        print(head);
        cout << "-------------------------------------------------" << endl;
        cout << "开始删除(这里删除第2个元素)............................" << endl;
        del(head, 2);
        cout << "删除操作完毕!" << endl;
        cout << "删除后打印线性表中的所有数据:";
        print(head);
        destroy(head);
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:双向链表(含循环双链表)

        本文链接:https://www.haomeiwen.com/subject/cdxghktx.html