双向链表实现

双向链表:对比单向链表,双向链表中,一个结点不仅知道他的后继,还知道他的前驱,这就使得双向链表在操作上比单项链表更为简单,效率更高

注:头结点的data无任何意义,所以填0即可

空的双向链表(head 的 prev 和 next 都指向头结点)


非空双向链表(结构如下图所示)




头文件 DLinkList.h

#pragma once

typedef char  DLinkType;

typedef struct DLinkNode{
    DLinkType data;
    struct DLinkNode* prev;
    struct DLinkNode* next;
}DLinkNode;

/*
 *双向链表初始化
 */
void DLinkListInit(DLinkNode** head);

/*
 *尾插
 */
void DLinkListPushBack(DLinkNode* head, DLinkType value);

/*
 *尾删
 */
void DLinkListPopBack(DLinkNode* head);

/*
 *头插
 */
void DLinkListPushiFront(DLinkNode* head, DLinkType value);

/*
 *头删
 */
void DLinkListPopFront(DLinkNode* head);

/*
 *查找指定元素的位置
 */
DLinkNode* DLinkListFind(DLinkNode* head, DLinkType to_find);

/*
* 在指定位置的前面插入一个元素
*/
void DLinkListInsert(DLinkNode* head, DLinkNode* pos, DLinkType to_insert);

/*
 *在指定位置的后面插入一个元素
 */
void DLinkListInsertAfter(DLinkNode* head, DLinkNode* pos, DLinkType to_insert);

/*
 *删除指定位置的元素
 */
void DLinkListErase(DLinkNode* head, DLinkNode* pos);

/*
 *删除指定元素
 */
void DLinkListRemove(DLinkNode* head, DLinkType to_delete);

/*
 *删除所有元素
 */
void DLinkListRemoveAll(DLinkNode* head);

/*
 *求双向链表的长度
 */
size_t DLinkListSize(DLinkNode* head);

/*
 *判断双向链表是否为空
 */
int DLinkEmpty(DLinkNode* head);

.c 文件 DLinkList.c

head头指针指向头结点,不可能为空,如果为空则是非法输入

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

#define FUNCTION printf("\n===================================%s======================================\n", __FUNCTION__)

DLinkNode* CreatDLinkNode(DLinkType value){
    DLinkNode* new_node = (DLinkNode*)malloc(sizeof(DLinkNode));
    if(new_node == NULL)
    {
        return NULL;
    }
    new_node->data = value;
    new_node->prev = new_node;
    new_node->next = new_node;
    return new_node;
}

void DestroyDLinkNode(DLinkNode* to_destroy_node){
    if(to_destroy_node == NULL){
        return;
    }
    free(to_destroy_node);
}

void DLinkListInit(DLinkNode** head){
    if(head == NULL){
        return;
    }
    *head = CreatDLinkNode(0);
}

void DLinkListPushBack(DLinkNode* head, DLinkType value){
    if(head == NULL){
        return;
    }
    DLinkNode* tail = head->prev;;
    DLinkNode* new_node = CreatDLinkNode(value);
    if(new_node == NULL){
        return;
    }
    new_node->data = value;
    head->prev = new_node;
    new_node->next = head;
    tail->next = new_node;
    new_node->prev = tail;
}

void DLinkListPopBack(DLinkNode* head){
    if(head == NULL){
        return;
    }
    DLinkNode* tail = head->prev;
    head->prev = tail->prev;
    head->prev->next = head;
    DestroyDLinkNode(tail);
}

void DLinkListPushFront(DLinkNode* head, DLinkType value){
    if(head == NULL){
        return;
    }
    DLinkNode* new_node = CreatDLinkNode(value);
    if(new_node == NULL)
    {
        return;
    }
    DLinkNode* next = head->next;
    head->next = new_node;
    new_node->prev = head;
    new_node->next = next;
    next->prev = new_node;
}

void DLinkListPopFront(DLinkNode* head){
    if(head == NULL){
        return;
    }
    DLinkNode* to_destroy_node = head->next;
    head->next = to_destroy_node->next;
    to_destroy_node->next->prev = head;
    DestroyDLinkNode(to_destroy_node);
}

DLinkNode* DLinkListFind(DLinkNode* head, DLinkType to_find){
    if(head == NULL){
        return NULL;
    }
    DLinkNode* cur = head->next;
    for(; cur != head; cur = cur->next){
        if(cur->data == to_find){
            return cur;
        }
    }
}

void DLinkListInsert(DLinkNode* head, DLinkNode* pos, DLinkType value){
    if(head == NULL || pos == NULL){
        return;
    }
    DLinkNode* cur = head->next;
    for(; cur != head; cur = cur->next){
        if(cur == pos){
            DLinkNode* prev = CreatDLinkNode(value);
            cur->prev->next = prev;
            prev->prev =  cur->prev;
            prev->next = cur;
            cur->prev = prev;
            return;
        }
    }
}

void DLinkListInsertAfter(DLinkNode* head, DLinkNode* pos , DLinkType value){
    if(head == NULL || pos == NULL){
        return;
    }
    DLinkNode* cur = head->next;
    for(; cur != head; cur = cur->next){
        if(cur == pos){
            DLinkNode* next = CreatDLinkNode(value);
            next->next = cur->next;
            next->prev = cur;
            cur->next = next;
            next->next->prev = next;
            return;
        }
    }
}

void DLinkListErase(DLinkNode* head, DLinkNode* pos){
    if(head == NULL || pos == NULL){
        return;
    }
    DLinkNode* cur = head->next;
    for(; cur != head; cur = cur->next){
        if(cur == pos){
            DLinkNode* prev = cur->prev;
            prev->next = cur->next;
            cur->next = prev;
            DestroyDLinkNode(cur);
            return;
        }
    }
}

void DLinkListRemove(DLinkNode* head, DLinkType to_delete){
    if(head == NULL){
        return;
    }
    DLinkNode* cur = head->next;
    for(; cur != head; cur = cur->next){
        if(cur->data == to_delete){
            DLinkNode* prev = cur->prev;
            prev->next = cur->next;
            cur->next = prev;
            DestroyDLinkNode(cur);
            return;
        }
    }
}

void DLinkListRemoveAll(DLinkNode* head){
    if(head == NULL){
        return;
    }
    DLinkNode* cur = head->next;
    for(; cur != head; cur = head->next){
        head->next = cur->next;
        DestroyDLinkNode(cur);
    }
}

size_t DLinkListSize(DLinkNode* head){
    if(head == NULL){
        return 0;
    }
    size_t ret = 0;
    DLinkNode* cur = head->next;
    for(; cur != head; cur = cur->next){
        ret++;
    }
    return ret;
}

int DLinkListEmpty(DLinkNode* head){
    if(head == NULL){
        return 0;
    }
    if(head->prev == head && head->next == head)
    {
        return 0;
    }
    return 1;
}

//以下为测试代码


void Print(DLinkNode* head, char* str){
    DLinkNode* cur = head->next;
    printf("[%s]\n", str);
    while(cur != head)
    {
        printf("[%c] ", cur->data);
        cur = cur->next;
    }
    printf("\n");
}


void TestInit()
{
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    printf("head->data expected 0, actrue is %d\n", head->data);
    printf("head->prev expected %p, actrue is %p\n", head, head->prev);
    printf("head->next expected %p, actrue is %p\n", head, head->next);
}

void TestPushBack(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushBack(head, 'a');
    DLinkListPushBack(head, 'b');
    DLinkListPushBack(head, 'c');
    DLinkListPushBack(head, 'd');
    Print(head,"尾插四个元素");
}

void TestPopBack(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushBack(head, 'a');
    DLinkListPushBack(head, 'b');
    DLinkListPushBack(head, 'c');
    DLinkListPushBack(head, 'd');
    DLinkListPopBack(head);
    DLinkListPopBack(head);
    Print(head,"尾删两个元素");
    DLinkListPopBack(head);
    DLinkListPopBack(head);
    Print(head,"再尾删两个元素");
    DLinkListPopBack(head);
    Print(head,"尾差空链表");
}

void TestPushFront(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    DLinkListPushFront(head, 'c');   
    DLinkListPushFront(head, 'd');   
    Print(head,"头插四个元素");
}

void TestPopFront(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    DLinkListPushFront(head, 'c');   
    DLinkListPushFront(head, 'd');   
    DLinkListPopFront(head);
    DLinkListPopFront(head);
    Print(head,"头删两个元素");
    DLinkListPopFront(head);
    DLinkListPopFront(head);
    Print(head,"再头删两个元素");
    DLinkListPopFront(head);
    Print(head,"头删空链表");
}

void TestFind(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    DLinkListPushFront(head, 'c');   
    DLinkListPushFront(head, 'd');   
    DLinkNode* ret;
    ret = DLinkListFind(head, 'a');
    printf("expected %p, actrue %p\n", head->prev, ret);
    ret = DLinkListFind(head, 'd');
    printf("expected %p, actrue %p\n", head->next, ret);
}

void TestInsert(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    DLinkListPushFront(head, 'c');   
    DLinkListPushFront(head, 'd');   
    Print(head, "头插四个元素");
    DLinkNode* pos;
    pos = DLinkListFind(head, 'a');
    DLinkListInsert(head, pos, 'X');
    Print(head, "指定位置前插入一个元素");
    pos = DLinkListFind(head, 'd');
    DLinkListInsert(head, pos, 'Y');
    Print(head, "指定位置前插入一个元素");

}

void TestInsertAfter(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    DLinkListPushFront(head, 'c');   
    DLinkListPushFront(head, 'd');   
    Print(head, "头插四个元素");
    DLinkNode* pos;
    pos = DLinkListFind(head, 'a');
    DLinkListInsertAfter(head, pos, 'X');
    Print(head, "指定位置后插入一个元素");
    pos = DLinkListFind(head, 'd');
    DLinkListInsertAfter(head, pos, 'Y');
    Print(head, "指定位置后插入一个元素");
}

void TestErase(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    DLinkListPushFront(head, 'c');   
    DLinkListPushFront(head, 'd');   
    Print(head, "头插四个元素");
    DLinkNode* pos;
    pos = DLinkListFind(head, 'a');
    DLinkListErase(head, pos);
    Print(head, "删除a");
    pos = DLinkListFind(head, 'd');
    DLinkListErase(head, pos);
    Print(head, "删除d");
    pos = DLinkListFind(head, 'A');
    DLinkListErase(head, pos);
    Print(head, "删除没有的元素");
}

void TestRemove(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    DLinkListPushFront(head, 'c');   
    DLinkListPushFront(head, 'd');   
    Print(head, "头插四个元素");
    DLinkListRemove(head, 'a');
    Print(head, "删除a");
    DLinkListRemove(head, 'd');
    Print(head, "删除d");
    DLinkListRemove(head, 'A');
    Print(head, "删除没有的元素");
}

void TestRemoveAll(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    DLinkListPushFront(head, 'c');   
    DLinkListPushFront(head, 'd');   
    Print(head, "头插四个元素");
    DLinkListRemoveAll(head);
    Print(head, "删除所有元素");
    DLinkListRemoveAll(head);
    Print(head, "对空链表进行删除");
}

void TestSize(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    size_t ret;
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    Print(head, "头插两个元素");
    ret = DLinkListSize(head);
    printf("expected 2, actrue %u\n", ret);
    DLinkListPushFront(head, 'c');   
    DLinkListPushFront(head, 'd');   
    Print(head, "头插四个元素");
    ret = DLinkListSize(head);
    printf("expected 4, actrue %u\n", ret);
}

void TestEmpty(){
    FUNCTION;
    DLinkNode* head;
    DLinkListInit(&head);
    int ret;
    ret = DLinkListEmpty(head);
    printf("expected 0, actrue %d\n", ret);
    DLinkListPushFront(head, 'a');   
    DLinkListPushFront(head, 'b');   
    Print(head, "头插两个元素");
    ret = DLinkListEmpty(head);
    printf("expected 1, actrue %d\n", ret);

}

int main()
{
    TestInit();
    TestPushBack();
    TestPopBack();
    TestPushFront();
    TestPopFront();
    TestFind();
    TestInsert();
    TestInsertAfter();
    TestErase();
    TestRemove();
    TestRemoveAll();
    TestSize();
    TestEmpty();
    return 0;
}

运行结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值