双向链表的实现(头插尾插和删除、遍历)

关于双向链表和循环链表,维基上的解释是:

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

循环链表是一种链式存储结构,它的最后一个结点指向头结点,形成一个环。因此,从循环链表中的任何一个结点出发都能找到任何其他结点。循环链表的操作和单链表的操作基本一致,差别仅仅在于算法中的循环条件有所不同。

#include <stdio.h>
#include <stdlib.h>
//定义链接节点结构 包含了节点的数据域、前后指针域
typedef struct node {
    char *data;
    struct node *next;
    struct node *prior;
} node;
//定义链表结构 包含链表头节点指针、链表长度
typedef struct {
    node *head;
    int len;
}LinkedList;
//初始化双向链表 包括生成表头,初始化表长度
LinkedList * init() {
    LinkedList *L = NULL;
    L = (LinkedList *)malloc(sizeof(LinkedList));
    node *head =  (node *)malloc(sizeof(node));
    head->next = head;
    head->prior= head;
    L->head = head;
    L->len = 0;
    return L;
}
//向链表头部插入数据
void add_to_head(LinkedList *L, char *data) {
    node *dnode = (node *)malloc(sizeof(node));
    dnode->data = data;
    dnode->next = L->head->next;
    dnode->prior= L->head;
    L->head->next->prior = dnode;
    L->head->next = dnode;
    L->len++;
}
//向链表尾部插入数据
void add_to_tail(LinkedList *L, char *data) {
    node *dnode = (node *)malloc(sizeof(node));
    dnode->data = data;
    dnode->next = L->head;
    dnode->prior= L->head->prior;
    dnode->prior->next = dnode;
    L->head->prior = dnode;
    L->len++;
}
//从链表中删除下标为QQ交易的节点,index从0开始。
//index在链表前半段时从头部遍历 index在链表后半段时从头部逆向遍历
void del_data(LinkedList *L, int index) {
    if(index > L->len) {
        printf("index error");
        return;
    }
    node * node_tmp = NULL;
    int i=0;
    if(index < L->len/2) {
        node_tmp = L->head->next;
        for(i=0; i<index; i++) {
            node_tmp = node_tmp->next;
        }
    } else {
        node_tmp = L->head->prior;
        for(i=0; i<L->len-index; i++) {
            node_tmp = node_tmp->prior;
        }
    }
    node_tmp->prior->next = node_tmp->next;
    node_tmp->next->prior = node_tmp->prior;
    free(node_tmp);
    L->len--;
}
//遍历并打印链表(正向)
void foreach(LinkedList *L) {
    node *n = L->head->next;
    while(n != L->head) {
        printf("%s\n", n->data);
        n = n->next;
    }
}
//遍历并打印链表(逆向)
void rforeach(LinkedList *L) {
    node *n = L->head->prior;
    while(n != L->head) {
        printf("%s\n", n->data);
        n = n->prior;
    }
}
int main() {
    LinkedList *L;
    L = init();
    add_to_tail(L, "C");
    add_to_tail(L, "C++");
    add_to_tail(L, "C#");
    add_to_tail(L, "java");
    add_to_tail(L, "php");
    add_to_tail(L, "python");
    add_to_tail(L, "ruby");
    add_to_tail(L, "object-c");
    printf("打印链表\n");
    foreach(L);
    printf("删除index=2的元素 打印链表\n");
    del_data(L, 2);
    foreach(L);
    printf("逆向打印链表\n");
    rforeach(L);
    return;
}

以上代码的运行结果:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值