双链表

Posted blairgrowing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双链表相关的知识,希望对你有一定的参考价值。

循环链表

  将单链表的形式稍作改变,不让最后一个结点的指针为NULL,而让它指向头一个结点,这样就得到了循环链表。

   它的优点是:从循环链表中任一结点出发,都能访问遍所有结点。

 

双链表

  优点:既可以方便的找前驱,也可以找后继。

双向链表

  双向链表中,每个结点有两个指针域,一个指向直接后继元素结点,另一个指向直接前趋元素结点。

结构体

typedef char DataType;
struct DoubleNode{
    DataType data;
    DoubleNode* prev;
    DoubleNode* next;
};
typedef DoubleNode* PDoubleNode;

初始化双链表

//初始化链表,大小为可以储存n个元素
PDoubleNode InitList(PDoubleNode head,int n){
    PDoubleNode p,s;
    head = (DoubleNode*)malloc(sizeof(DoubleNode));//分配内存
    if(head==NULL){
        return NULL;
    }
    //头节点的初始化
    head->prev =NULL;
    head->next = NULL;
    p=head;
    //输入n个元素
    for (int i = 0; i < n; i++)
    {
        s= (PDoubleNode)malloc(sizeof(DoubleNode));
        if (s==NULL)
        {
            exit(0);
        }
        cout<<"Enter a value"<<endl;
        cin>>s->data;
        //指针指向
        s->next=NULL;
        p->next = s;
        s->prev =p;
        p=s;//p指向尾节点
    }

    return head;
}

 

插入元素

  添加至表头

 

           技术图片

 

  换句话说,假设新元素节点为 temp,表头节点为 head,则需要做以下 2 步操作即可:

    1.   temp->next=head; head->prior=temp;
    2.   将 head 移至 temp,重新指向新的表头;

 

  添加至表的中间位置

    1.   新节点先与其直接后继节点建立双层逻辑关系;
    2.   新节点的直接前驱节点与之建立双层逻辑关系;

技术图片

 

  添加至表尾

    1.   找到双链表中最后一个节点;
    2.   让新节点与最后一个节点进行双层逻辑关系;

 

                       技术图片

PDoubleNode insertNode(PDoubleNode head,DataType data,int pos){
    PDoubleNode p=head;
    PDoubleNode q =(PDoubleNode)malloc(sizeof(DoubleNode));
    q->data=data;
    q->next=NULL;
    q->prev=NULL;
    //插入到表头需要特殊考虑
    if(pos==1){
        q->next=head;
        head->prev=q;
        head=q;
    }else
    {
        //找到要插入位置的前一个结点
        for (int i = 1; i < add-1; i++)
        {
            p=p->next;
        }
        //判断条件为真,说明插入位置为链表尾
        if (p->next==NULL)
        {
            p->next=q;
            q->prev=p;
        }else
        {
            p->next->prev=q;
            q->next=p->next;
            p->next=q;
            q->prev=p;
        }
    }
    return head;
}

删除节点

  双链表删除结点时,只需遍历链表找到要删除的结点,然后将该节点从表中摘除即可。

 

           技术图片

 

 

//删除节点
PDoubleNode deleteNode(PDoubleNode head,DataType data)
{
    PDoubleNode p=head;
    while (p)
    {
        if (p->data==data)
        {
            p->prev->next=p->next;            
            p->next->prev=p->prev;
            free(p);
            return head;
        }
        p=p->next;
    }
    cout<<"not found"<<endl;
    return head;
}

查找节点

  通常,双向链表同单链表一样,都仅有一个头指针。因此,双链表查找指定元素的实现同单链表类似,都是从表头依次遍历表中元素。

int selectElem(PDoubleNode head,DataType data){
    PDoubleNode p = head;
    int i=1;
    while (p)
    {
       if(p->data==data){
           return i;
       }
       i++;
       p=p->next;
    }
    return -1;
}

修改节点

PDoubleNode  amendElement(PDoubleNode head,int add,DataType newData){
    PDoubleNode p = head;
    for (int i = 0; i < add; i++)
    {
        p=p->data;
    }
    p->data=newData;
}

 

 

           

 

           

 

 

 

以上是关于双链表的主要内容,如果未能解决你的问题,请参考以下文章

基础数据结构---双链表go语言的代码实现

双链表代码实现和讲解

(王道408考研数据结构)第二章线性表-第三节2:双链表的定义及其操作(插入和删除)

数据结构-编程实现一个双链表的建立,双链表的打印,双链表的测长

数据结构(双链表)

双链表删除一个节点