双向链表List_数据结构_C语言实现

前言单向链表

单链表节点中只有一个指向其后继的指针,这使得单链表只能从头节点依次顺序地向后遍历。若要访问某个节点得前驱节点(插入、删除操作时),只能从头开始遍历

  • 为了克服单向链表的缺点,引入了双向链表,双向链表节点中有两个next和prev,分别指向下一个节点地址和上一个节点地址
如图理解:

双向链表理解图

按位置前插入元素:

前插元素

删除元素:

删除元素

线性表链式存储结构,双向链表的实现

定义声明函数:
/**
 *C实现:定义声明函数
 */
#ifndef CHAIN_H_INCLUDED
#define CHAIN_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
//双向链表
typedef struct ListNode_s{  //节点结构
    int data;               //数据
    struct ListNode_s* next;//指向下一个节点地址
    struct ListNode_s* prev;//指向上一个节点地址
}LIST_NODE_S;
typedef struct List_s{  //链表结构
    LIST_NODE_S* head;  //头节点指针
    LIST_NODE_S* tail;  //尾节点指针
    LIST_NODE_S* frwd;  //应用于迭代
}LIST_S;
//初始化链表
void list_s_init(LIST_S* list);
//释放化链表
void list_s_deinit(LIST_S* list);
//判断链表空
int list_s_empty(LIST_S* list);
//追加元素
void list_s_append(LIST_S* list, int data);
//插入元素(位置按前插)
int list_s_insert(LIST_S* list, size_t pos, int data);
//删除元素(按位置删除)
int list_s_erase(LIST_S* list, size_t pos);
//删除元素(相同元素全删除)
void list_s_remove(LIST_S* list, int data);
//全删元素
void list_s_clear(LIST_S* list);
//查看元素(按位置取值)
int* list_s_at(LIST_S* list, size_t pos);
//元素数量
size_t list_s_size(LIST_S* list);
//正向迭代
void list_s_begin(LIST_S* list);
//向前迭
int* list_s_next(LIST_S* list);
//反向迭代
void list_s_reverse(LIST_S* list);
//向后迭
int* list_s_prev(LIST_S* list);
//当前迭代(当前值)
int* list_s_current(LIST_S* list);
//判断迭代结束
int list_s_end(LIST_S* list);

#endif //CHAIN_H_INCLUDED

声明函数实现:
/**
 *C实现:声明函数实现
 */
#include "chain.h"
 
 //创建节点
static LIST_NODE_S* create_lists_node(int data, LIST_NODE_S* next, LIST_NODE_S* prev){
    LIST_NODE_S* node = malloc(sizeof(LIST_NODE_S));
    node->data = data;
    node->next = next;
    node->prev = prev;
    return node;
}
//销毁节点
static LIST_NODE_S* destroy_lists_node(LIST_NODE_S* node, LIST_NODE_S** prev){
    LIST_NODE_S* next = node->next;
    if(prev) *prev = node->prev;
    free(node);
    return next;
}
//初始化链表
void list_s_init(LIST_S* list){
    list->head = NULL;
    list->tail = NULL;
    list->frwd = NULL;
}
//释放化链表
void list_s_deinit(LIST_S* list){
    while(list->head){
        list->head = destroy_lists_node(list->head, NULL);
    }
    list->tail = NULL;
    list->frwd = NULL;
}
//判断链表空
int list_s_empty(LIST_S* list){
    return !list->head && !list->tail;
}
//追加元素
void list_s_append(LIST_S* list, int data){
    list->tail = create_lists_node(data, NULL, list->tail);
    if(list->tail->prev){
        list->tail->prev->next = list->tail;
    }else{
        list->head = list->tail;
    }
}
//插入元素(位置按前插)
int list_s_insert(LIST_S* list, size_t pos, int data){
    LIST_NODE_S* find = list->head;
    for(; find; find = find->next){
        if(!pos--){
            LIST_NODE_S* node = create_lists_node(data, find, find->prev);
            if(node->prev){
                node->prev->next = node;
            }else list->head = node;
            node->next->prev = node;
            return 1;
        }
    }
    return 0;
}
//删除元素(按位置删除)
int list_s_erase(LIST_S* list, size_t pos){
    LIST_NODE_S* find = list->head;
    for(; find; find = find->next){
        if(!pos--){
            LIST_NODE_S* prev = NULL;
            LIST_NODE_S* next = destroy_lists_node(find, &prev);
            if(prev){
                prev->next = next;
            }else list->head = next;
            if(next){
                next->prev = prev;
            }else list->tail = prev;
            return 1;
        }
    }
    return 0;
}
//删除元素(相同元素全删除)
void list_s_remove(LIST_S* list, int data){
    LIST_NODE_S* find = list->head;
    LIST_NODE_S* next = NULL;
    for(; find; find = next){
        next = find->next;
        if(find->data == data){
            LIST_NODE_S* prev = NULL;
            LIST_NODE_S* next = destroy_lists_node(find, &prev);
            if(prev){
                prev->next = next;
            }else list->head = next;
            if(next){
                next->prev = prev;
            }else list->tail = prev;
        }
    }
}
//全删元素
void list_s_clear(LIST_S* list){
    list_s_deinit(list);
}
//查看元素(按位置取值)
int* list_s_at(LIST_S* list, size_t pos){
    LIST_NODE_S* find = list->head;
    for(; find; find = find->next){
        if(!pos--) return &find->data;
    }
    return NULL;
}
//元素数量
size_t list_s_size(LIST_S* list){
    size_t size = 0;
    LIST_NODE_S* find = list->head;
    for(; find; find = find->next)size++;
    return size;
}
//正向迭代
void list_s_begin(LIST_S* list){
    list->frwd = list->head;
}
//向前迭
int* list_s_next(LIST_S* list){
    int* data = &list->frwd->data;
    list->frwd = list->frwd->next;
    return data;
}
//反向迭代
void list_s_reverse(LIST_S* list){
    list->frwd = list->tail;
}
//向后迭
int* list_s_prev(LIST_S* list){
    int* data = &list->frwd->data;
    list->frwd = list->frwd->prev;
    return data;
}
//当前迭代(当前值)
int* list_s_current(LIST_S* list){
    return &list->frwd->data;
}
//判断迭代结束
int list_s_end(LIST_S* list){
    return !list->frwd;
}

实现函数验证:
/**
 *C实现:实现函数验证
 */
#include "chain.h"

int main()
{
    int i;
	LIST_S lists;
    list_s_init(&lists);//初始
    for(i = 0; i < 10; i++){
        list_s_append(&lists, (i+1)*10);//追加
    }
    list_s_insert(&lists, 2, 25);//前插(2的位置是30前插)
    list_s_erase(&lists, 3);//位置删除(3的位置还是30将删)
    //追加(为了测相同数据删除)
	list_s_append(&lists, 25);
    //相同数据删除(2的位置25删除)与(后面追加的25删除)
	list_s_remove(&lists, 25);
	//位置取数据,(2的位置当前是40)
    printf("取2位置=%d\n", *list_s_at(&lists, 2));
    //正向遍历
	list_s_begin(&lists);
    //返回frwd(返回当前是否是头数据)
	printf("frwd头数据=%d\n", *list_s_current(&lists));
    while(!list_s_end(&lists)){//判断结束frwd迭代
        printf("%d\n", *list_s_next(&lists));//向前迭代观察数据
    }
	printf("数量=%d\n", list_s_size(&lists));//元素数量
	//全销毁数据(就是调用list_s_deinit)
    list_s_clear(&lists);
    printf("数据为空%d\n", !list_s_empty(&lists));//为空0
	printf("数量=%d\n", list_s_size(&lists));//元素数量
    list_s_deinit(&lists);//释放
	return 0;
}

结果:

运行结果

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值