动手实现 数据结构 之 “双向链表”

C 语言方式实现了 双向链表的 

插入

删除

查找

头部出栈

尾部出栈

头部插入

尾部插入


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

typedef int bool;

typedef struct Node {
    struct Node * front;
    struct Node * back;
    int data;
}Node;

typedef struct List {
    struct Node * begin;// 第一个元素
    struct Node * end;  // 最后一个元素的后一个元素
}List;

// 使用链表前必须 调用Init
void Init(struct List * list) {
    struct Node * node = (struct Node*)malloc(sizeof(struct Node));
    node->front = NULL;
    node->back = NULL;
    // 当链表为空时预留一个元素(只是为了增加效率和设计上的方便)
    list->begin = node;
    list->end = list->begin;
}

bool IsEmpty(struct List * list) {
    return list->end == list->begin;
}

// 在链表中从头到尾 查找第一个数据为data 的节点
struct Node* SearchList(struct List * list, int data) {
    for(struct Node* p=list->begin; p != list->end; p=p->back) {
        if(p->data == data) return p;
    }
    return NULL;
}

void PushFront(struct List * list, int data) {
    struct Node * node = (struct Node*)malloc(sizeof(struct Node));
    node->data = data;
    
    node->front = NULL;
    node->back = list->begin;
    
    list->begin->front= node;
    list->begin = node;
}

void PushBack(struct List * list, int data) {
    list->end->data = data;
    
    struct Node * node = (struct Node*)malloc(sizeof(struct Node));
    node->back = NULL;
    
    node->front = list->end;
    list->end->back = node;
    list->end = node;
}

int PopFront(struct List * list) {
    int result = list->begin->data;
    struct Node * p = list->begin;
    list->begin = list->begin->back;
    list->begin->front = NULL;
    free(p);
    return result;
}

int PopBack(struct List * list) {
    struct Node * last = list->end->front;
    int result = last->data;
    
    struct Node * p = list->end;
    last->back = NULL;
    list->end = last;
    free(p);
    return result;
}

// 在节点 pos 后插入一个节点 数据为data
void InsertNodeTo(struct List * list, struct Node* pos, int data) {
    struct Node * node = (struct Node*)malloc(sizeof(struct Node));
    node->data = data;
    
    node->front = pos;
    node->back = pos->back;
    
    pos->back = node;
    node->back->front = node;
    
    if(list->end == pos)
        list->end = pos;
}

// 删除 list 中 pos 节点 (end 前一个元素是最后一个元素,不能删除 end 因为 end 是辅助节点不用于存储)
void RemoveNodeFrom(struct List * list, struct Node* pos) {
    if(pos == list->begin) PopFront(list);
    else if(pos == list->end->front) PopBack(list);
    else {
        pos->front->back = pos->back;
        pos->back->front = pos->front;
        free(pos);
    }
}

void PrintList(struct List * list) {
    for(struct Node* p=list->begin; p != list->end; p=p->back) {
        printf("%d  ", p->data);
    }
    printf("\n");
}

// 使用完需要使用Destroy将内存释放
void Destroy(struct List * list) {
    struct Node* back;
    for(struct Node* p=list->begin; p != list->end; p=back) {
        back = p->back;
        free(p);
    }
    if(list->end != NULL) free(list->end);
}

int main(void)
{
    List list;
    Init(&list);
    
    PushBack(&list, 1);
    PushBack(&list, 2);
    PushBack(&list, 3);
    PushBack(&list, 4);
    PushBack(&list, 5);
    
    PushFront(&list, 0);
    
    Node * pos = SearchList(&list, 3);
    
    InsertNodeTo(&list, pos, 9);
    
    PrintList(&list);
    
    printf("Pop front %d\n", PopFront(&list));
    
    printf("Pop back %d\n", PopBack(&list));
    
    RemoveNodeFrom(&list, list.begin);
    
    struct Node* p;
    for(p=list.end->front; p!=list.begin; p=p->front) {
        printf("%d  ", p->data);
    }
    printf("%d\n", p->data);
    
    Destroy(&list);
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值