双向链表

1.双向链表的优点:双向链表的主要优点是对于任意给的结点,都可以很轻易的获取其前结点和后结点,其主要缺点是每个结点需要保存next和prev两个属性,因此需要更多的空间开销,同时结点的插入与删除操作也将更加耗时,因为需要操作更多的指向操作

2.双向链表的结构

  (1)单个节点的结构:

                    

  (2)数据的结构:

                 

  (3)尾部插入节点:

    

  (4)中间插入

  

3.双向链表的具体操作

#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//节点结构
typedef struct LinkedList
{
    struct LinkedList * prior;
    int data;
    struct LinkedList * next;
}LinkedList, *PLinkedList;
//双链表的创建函数
PLinkedList initLine(PLinkedList head);
//输出双链表的函数
void Display(PLinkedList head);
//插入节点
void InsertElem(PLinkedList head, int data);
//删除指定节点
void DeleteElem(PLinkedList head, int data);
int main() 
{
    //创建一个头指针
    PLinkedList    head = NULL;
    //调用链表创建函数
    head = initLine(head);
    //输出创建好的链表
    Display(head);
    //尾部插入一个节点
    InsertElem(head, 10);
    Display(head);
    //删除尾部的节点
    DeleteElem(head, 10);
    Display(head);

    //显示双链表的优点
    printf("链表中第 4 个节点的直接前驱是:%d", head->next->next->next->prior->data);

    
    system("pause");
    return 0;
}

void InsertElem(PLinkedList head, int data)
{
    if (head == NULL){
        printf("The list is empty.
");        //  头结点为空,则无法插入
        return;
    }
    PLinkedList tmpHead = head;        //  创建一个临时的头结点指针
    while (tmpHead->next!=NULL)
    {
        tmpHead = tmpHead->next;
    }
    if (tmpHead->next == NULL)
    {
        PLinkedList addition = (PLinkedList)malloc(sizeof(LinkedList));
        _ASSERT(addition != NULL);
        addition->data = data;        //  数据域赋值
        addition->next = tmpHead->next;        //  后向指针连接
        tmpHead->next = addition;
        addition->prior = tmpHead;            //  将插入结点的front 指向头结点
    }
}

void DeleteElem(PLinkedList head, int data)
{
    if (head == NULL){
        printf("The list is empty.
");
        return;
    }
    PLinkedList tmpHead = head;
    while (tmpHead->next != NULL){
        tmpHead = tmpHead->next;
        if (tmpHead->data == data)
        {
            //此节点为最后一个节点
            if (tmpHead->next == NULL)
            {
                tmpHead->prior->next = NULL;        //  将被删结点的上一个结点的next 指针指向 NULL
                tmpHead->prior->prior = head;        //  将被删结点的上一个结点的prior指向头节点
            }
            //删除中间节点
            else
            {
                tmpHead->prior->next = tmpHead->next;        //  将被删结点的上一个结点的next 指针指向 被删结点的下一个结点
                tmpHead->next->prior = tmpHead->prior;        //  将被删结点的下一个结点的 front 指针指向 被删结点的上一个结点
            }
            break;
        }
    }
    free(tmpHead);        //  释放内存
}


PLinkedList initLine(PLinkedList head)
{
    //创建一个首元节点,链表的头指针为head
    head = (PLinkedList)malloc(sizeof(LinkedList));
    //对节点进行初始化
    head->prior = NULL;
    head->next = NULL;
    head->data = 1;
    //声明一个指向首元节点的指针,方便后期向链表中添加新创建的节点
    PLinkedList list = head;
    for (int i = 2; i <= 5; i++) {
        //创建新的节点并初始化
        PLinkedList body = (PLinkedList)malloc(sizeof(LinkedList));
        body->prior = NULL;
        body->next = NULL;
        body->data = i;
        //新节点与链表最后一个节点建立关系
        list->next = body;
        body->prior = list;
        //list永远指向链表中最后一个节点
        list = list->next;
    }
    //返回新创建的链表
    return head;
}

void Display(PLinkedList head)
{
    PLinkedList temp = head;
    while (temp) {
        //如果该节点无后继节点,说明此节点是链表的最后一个节点
        if (temp->next == NULL) {
            printf("%d
", temp->data);
        }
        else{
            printf("%d <-> ", temp->data);
        }
        temp = temp->next;
    }
}
111
原文地址:https://www.cnblogs.com/zwj-199306231519/p/13032107.html