二叉树之下

线性表之双向链表

2019-03-12  本文已影响17人  此间不留白

基本概念

在之前的学习中,已经学习了单向链表及其实现,在单向链表中,查找一个数据,只能从某个结点出发,顺着指针往后查找其他结点,若需要查找结点的前驱结点,只能从表头指针重新出发。在单向链表中,查找一个结点的直接后继结点,其时间复杂度为O(1),而查找其直接前驱结点,需要的时间复杂度为O(n),为了克服这种缺点,特地引入了双向链表。
双向链表与单向链表相比,双向链表有两个指针域,一个指向其直接后继,另一个指向其直接前驱,其结构如下图所示:

双向链表
双向链表的结点可以用以下结构体定义
typedef struct dulNode {
    int pData;  //数据域
    struct dulNode *next; //后继结点
    struct dulNode *pre;  //前驱结点
}dulNode, *dulList;

双向链表的接口及其实现

接口定义

接口定义如下代码所示:

#pragma once
#ifndef DOUBLELINKLIST_H
#define DOUBLELINKLIST_H
typedef struct dulNode {
    int pData;  //数据域
    struct dulNode *next; //后继结点
    struct dulNode *pre;  //前驱结点
    
}dulNode, *dulList;

dulList initDulList(); //初始化
dulList insertDulList(dulList list, int i, int elem); //位置i处插入元素elem
dulList deleteDulList(dulList list, int i);//删除i处的结点
int locateDulList(dulList list, int elem); //查找元素elem的位置‘
void dulList_trave(dulList list); //遍历链表
void freeDulList(dulList list); //销毁链表
dulList updateDulList(dulList list, int i, int elem); //修改i处的元素
int getLength(dulList list);
#endif // !DOUBLELINKLIST_H

接口实现

dulList initDulList()
{
    dulList list = (dulList)malloc(sizeof(dulNode));
    
    if (list)
    {
        list->next = list->pre = NULL;
        list->pData = NULL;
    
        return list;
    }
    else
        return NULL;
}

以上过程可以由以下代码实现

dulList insertDulList(dulList list, int i, int elem)
{
    dulList temp = (dulList)malloc(sizeof(dulNode));
    temp->pData = elem;
    temp->next = NULL;
    temp->pre = NULL;
    
    if (i<1||i>getLength(list)+1)
    {
        printf("位置无效!");
        exit(0);
        
    }
    else if (i == 1)
    {
        
        temp->next = list;
        list->pre = temp;
        list = temp;
        
        
    }
    else
    {
         //找到插入位置的前一个结点
        dulList p = list;
        for (int j = 1; j < i-1; j++)
        {
            p = p->next;
        }
        //判断是否是尾
        if (p->next == NULL)
        {
            p->next = temp;
            temp->pre = p;
            
        }
        else
        {
            p->next->pre = temp;
            temp->next = p->next;
            p->next = temp;
            temp->pre = p;
            
        }

    }
    
    return list;
    

}

  1. 将被删除结点的后继指针赋值给其直接前驱结点的后继指针;
  2. 将被删除结点的前驱指针赋值给其直接后继结点的前驱指针。
    具体过程可由以下动态图所示:


    删除一个结点

以上过程的具体实现代码如下所示:

dulList deleteDulList(dulList list, int i)
{
    if (i<1 || i>getLength(list))
    {
        printf("位置错误!");
        exit(0);
    }
    dulList p = list;
    for (int j = 0; j <i-1; j++)
    {
        p = p->next;
    }
    if (p!=NULL)
    {
        p->pre->next = p->next;
        p->next->pre = p->pre;
        free(p);
    }
    return list;

}

int locateDulList(dulList list, int elem)
{
    int index = 0;
    dulList p = list;
    while (p!=NULL)
    {
        
        if (p->pData == elem)
        {
            return index;
        }
        index++;
        p = p->next;
    }
    return -1;

}

dulList updateDulList(dulList list, int i, int elem)
{
    if (i < 1 || i>getLength(list))
    {
        printf("无效位置!");
        exit(0);
    }
    dulList p = list;
    if (p != NULL)
    {
        for (int j = 1; j < i; j++)
        {
            p = p->next;
        }
        p->pData = elem;
        return list;
    }
    
    
}
int getLength(dulList list)
{
    int i = 0;
    dulList p = list->next;
    while (p != NULL)
    {
        i++;
        p = p->next;
    }
    return i;
}
void dulList_trave(dulList list)
{
    dulList p = list;
    if (p->next == NULL)
    {
        exit(0);
    }
    while (p->next)
    {
        if (p->next == NULL)
        {
            printf("%d", p->pData);

        }
        else
        {
            printf("%d->", p->pData);
        }
        p = p->next;
    }
}

void freeDulList(dulList list)
{
    dulList p = list;
    if (list)
    {
        exit(0);
    }
    while (list)
    {
        p = list;
        list = list->next;
        free(p);
    }
    

}

对双向链表的测试代码如下所示:

int main()
{
    
    struct dulList* list = initDulList();
    list = insertDulList(list, 1, 1);
    list = insertDulList(list, 2, 2);
    list = insertDulList(list, 3, 3);
    list = insertDulList(list, 4, 4);
    int index = locateDulList(list, 4);
    list = updateDulList(list, 4, 6);
    //printf("%d\n", index);
    freeDulList(list);
    //dulList_trave(list);
    system("pause");
    return 0;
}

教材:数据结构(C语言版)清华大学出版社
辅助学习网站:https://visualgo.net

上一篇下一篇

猜你喜欢

热点阅读