数据结构-双向链表

首先来看示意图

其实可以看到双向链表比单向链表可以更快的访问到前置元素 但是需要更多的空间 也就是我们拿空间换取了时间

 插入过程

首先是插入头结点

 

 

在其他位置插入节点

 

 

 

#ifndef DATAELEMENT_H_INCLUDED
#define DATAELEMENT_H_INCLUDED

 #define MAX_SIZE 255
 #define TRUE 1
 #define FALSE 0

 //1、定义数据元素
 //typedef int ElementType;
 /*
  * datas = {{1, ""}, {2, ""}, {3, ""}};
  */
 typedef struct{
    int id;
    char * name;
 }ElementType;

#endif // DATAELEMENT_H_INCLUDED

 

#ifndef DOUBLYLINKLIST_H_INCLUDED
#define DOUBLYLINKLIST_H_INCLUDED


#include <stdio.h>
#include <stdlib.h>
#include "DataElement.h"

/** 双向链表的结点,包含一个数据域,两个指针域 */
typedef struct DoublyNode{
    ElementType data;
    struct DoublyNode * prev;   //指向前缀结点
    struct DoublyNode * next;   //指向后继结点
}DoublyNode;

/** 双向链表 */
typedef struct DoublyLinkList{
    int length;
    DoublyNode * next;
}DoublyLinkList;

/** 向双向链表中的指定位置插入元素 */
void InsertDoublyLinkList(DoublyLinkList * dlList, int pos, ElementType element);

/** 删除并返回双向链表指定位置的元素 */
ElementType DeleteDoubyLinkList(DoublyLinkList * dlList, int pos);

/** 返回双向链表中指定位置的元素值 */
ElementType GetDoublyLinkListElement(DoublyLinkList * dlList, int pos);

/** 返回双向链表中某个结点的前置结点指针 */
DoublyNode * GetDoublyPrveNode(DoublyNode * node);

void PrintDoublyLinkList(DoublyLinkList * dlList);










#endif // DOUBLYLINKLIST_H_INCLUDED

 

#include "DoublyLinkList.h"

/** 向双向链表中的指定位置插入元素 */
void InsertDoublyLinkList(DoublyLinkList * dlList, int pos, ElementType element){
    //创建空结点
    DoublyNode * node = (DoublyNode*)malloc(sizeof(DoublyNode));
    node->data = element;
    node->prev = NULL;
    node->next = NULL;
    //在第一个位置插入结点
    if(pos == 1){
        //需要判断插入第一个位置并且插入时链表的长度为0
        if(dlList->length == 0){
            dlList->next = node;
            dlList->length++;
            return;
        }
        node->next = dlList->next;//对头节点和第一个元素进行操作
        dlList->next = node;
        node->next->prev = node;
        dlList->length++;
        return;
    }
    DoublyNode * currNode = dlList->next;
    for(int i = 1; currNode && i < pos - 1; i++){
        currNode = currNode->next;
    }
    if(currNode){
        node->prev = currNode;
        if(currNode->next){//如果前缀结点非空(因为空就表示没有后继结点了)
            //将插入位置处的前缀结点指向新结点
            currNode->next->prev = node;
        }
        node->next = currNode->next;
        currNode->next = node;
        dlList->length++;
    }
}

/** 删除并返回双向链表指定位置的元素 */
ElementType DeleteDoubyLinkList(DoublyLinkList * dlList, int pos){
    ElementType element;
    element.id = -999;
    if(pos == 1){
        DoublyNode * node = dlList->next;
        if(node){
            element = node->data;
            dlList->next = node->next;
            if(node->next){
                //如果有第二个结点,那么设置第二个节点的前缀结点为null
                node->next->prev = NULL;
            }
            free(node);
            dlList->length--;
        }
        return element;
    }
    DoublyNode * node = dlList->next;
    for(int i = 1; node && i < pos; i++){
        node = node->next;
    }
    if(node){
        element = node->data;
        if(node->next){
            node->next->prev = node->prev;
        }
        node->prev->next = node->next;
        free(node);
        dlList->length--;
    }
    return element;
}

/** 返回双向链表中指定位置的元素值 */
ElementType GetDoublyLinkListElement(DoublyLinkList * dlList, int pos){
    DoublyNode * node = dlList->next;
    for(int i = 1; node && i < pos; i++){
        node = node->next;
    }
    return node->data;
}

/** 返回双向链表中某个结点的前置结点指针 */
DoublyNode * GetDoublyPrveNode(DoublyNode * node){
    if(node)
        return node->prev;
    return NULL;
}

void PrintDoublyLinkList(DoublyLinkList * dlList){
    DoublyNode * node = dlList->next;
    if(!node || dlList->length == 0){
        printf("链表为空,没有内容可以打印!\n");
        dlList->length = 0;
        return;
    }
    for(int i = 0; i < dlList->length; i++){
        printf("%d\t%s\n", node->data.id, node->data.name);
        node = node->next;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值