双向链表的使用

一:双向链表头文件

#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct node_t
{
	datatype data;//数据域 
	struct node_t *next;//指向下一个节点的指针 next 下一个
	struct node_t *prior;//指向前一个节点的指针 prior 前一个
}link_node_t,*link_list_t;

//将双向链表的头指针和尾指针封装到一个结构体里 
//思想上有点像学的链式队列
typedef struct doublelinklist
{
	link_list_t head; //指向双向链表的头指针
	link_list_t tail; //指向双向链表的尾指针
	int len;
}double_node_t,*double_list_t;
//1.创建一个空的双向链表
double_list_t createEmptyDoubleLinkList();
//2.向双向链表的指定位置插入数据 post位置, data数据
int insertIntoDoubleLinkList(double_list_t p, int post, datatype data);
//3.遍历双向链表
void showDoubleLinkList(double_list_t p);
//4.删除双向链表指定位置的数据
int deletePostDoubleLinkList(double_list_t p, int post);
//5.判断双向链表是否为空
int isEmptyDoubleLinkList(double_list_t p);
//6.求双向链表的长度
int lengthDoubleLinkList(double_list_t p);
//7.查找指定数据出现的位置 data被查找的数据
int searchPostDoubleLinkList(double_list_t p,datatype data);
//8.修改指定位置的数据,post修改的位置 data被修改的数据
int changeDataDoubleLinkList(double_list_t p,int post, datatype data);
//9.删除双向链表中的指定数据 data代表删除所有出现的data数据
int deleteDataDoubleLinkList(double_list_t p, datatype data);

二:代码实现

#include "linkstack2.h"

// 1.创建一个空的双向链表
double_list_t createEmptyDoubleLinkList()
{
    double_list_t p = (double_list_t)malloc(sizeof(double_node_t));
    if (p == NULL)
    {
        perror("开辟失败:");
        return NULL;
    }
    // 开辟头结点空间
    p->len = 0;
    p->head = p->tail = (link_list_t)malloc(sizeof(link_node_t));
    if (p->head == NULL)
    {
        perror("开辟失败:");
        return NULL;
    }
    p->head->prior = NULL;
    p->head->next = NULL;
    return p;
}

// 2.向双向链表的指定位置插入数据 post位置, data数据
int insertIntoDoubleLinkList(double_list_t p, int post, datatype data)
{
    link_list_t temp = NULL;
    // 容错判断
    if (post < 0 || post > p->len)
    {
        perror("插入失败");
        return -1;
    }
    // 开辟节点存放数据
    link_list_t pnew = (link_list_t)malloc(sizeof(link_node_t));
    if (pnew == NULL)
    {
        perror("开辟失败:");
        return -1;
    }
    pnew->data = data;
    pnew->prior = NULL;
    pnew->next = NULL;
    // 将节点插入链表
    // 先对插入位置进行判断
    if (post == p->len) // 尾插
    {
        p->tail->next = pnew;
        pnew->prior = p->tail;
        p->tail = pnew; // 移动尾指针
       // printf("000\n");
    }
    else // 中间插
    {
        if (post < p->len / 2)
        {
            temp = p->head;
            for (int i = 0; i < post; i++)
                temp = temp->next;
        }
        else
        {
            temp = p->tail;
            for (int i = 0; i < p->len - post - 1; i++)
                temp = temp->prior;
        }
        // 进行插入操作(先练前面,后连后面)
        temp->prior->next = pnew;
        pnew->prior = temp->prior;
        pnew->next = temp;
        temp->prior = pnew;
    }

    // 长度加1
    p->len++;
    printf("000\n");
    return 0;
}

// 3.遍历双向链表
void showDoubleLinkList(double_list_t p)
{
    link_list_t temp = p->tail;
    while (temp != p->head)
    {
        printf("%d ", temp->data);
        temp = temp->prior;
    }

    // 正向遍历
    //  link_list_t temp=p->head;
    //  while(temp->next!=NULL)
    //  {
    //      temp=temp->next;
    //      printf("%d ",temp->data);
    //  }
}

// 4.删除双向链表指定位置的数据
int deletePostDoubleLinkList(double_list_t p, int post)
{
    link_list_t temp = NULL;
    // 容错判断
    if (isEmptyDoubleLinkList(p) || post < 0 || post >= p->len)
    {
        perror("空:");
        return -1;
    }
    // 对删除位置进行判断,两种情况
    if (post == p->len - 1) // 尾删
    {
        // 向前移动尾指针
        p->tail = p->tail->prior;
        // 释放被删除节点
        free(p->tail->next);
        p->tail->next = NULL;
    }
    else // 中间删除
    {
        if (post < p->len / 2)
        {
            temp = p->head;
            for (int i = 0; i < post; i++)
                temp = temp->prior;
        }
        else
        {
            temp = p->tail;
            for (int i = 0; i < p->len - post-1; i++)
                temp = temp->prior;
        }
        // 进行删除操作(先练前面,后连后面)
        temp->prior->next = temp->next;
        temp->next->prior = temp->prior;
    }
    // 长度减1
    p->len--;
}

// 5.判断双向链表是否为空
int isEmptyDoubleLinkList(double_list_t p)
{
    return p->len == 0;
}
//6.求双向链表的长度
int lengthDoubleLinkList(double_list_t p)
{
    return p->len;
}

//7.查找指定数据出现的位置 data被查找的数据
int searchPostDoubleLinkList(double_list_t p,datatype data)
{
    link_list_t temp=p->head;
    int sum=0;
    while(p->head!=NULL)
    {
        temp=temp->next;
        if(temp->data==data)
        return sum;
        sum++;
    }
    return -1;
}

//8.修改指定位置的数据,post修改的位置 data被修改的数据
int changeDataDoubleLinkList(double_list_t p,int post, datatype data)
{
    if(post<0||post>=p->len||isEmptyDoubleLinkList(p))
    {
        perror("空");
        return -1;
    }

    link_list_t temp=NULL;
    if (post == p->len - 1) 
    {
        p->tail = p->tail->prior;
        free(p->tail->next);
        p->tail->next = NULL;
    }
    else 
    {
        if (post < p->len / 2)
        {
            temp = p->head;
            for (int i = 0; i < post; i++)
                temp = temp->prior;
        }
        else
        {
            temp = p->tail;
            for (int i = 0; i < p->len - post-1; i++)
                temp = temp->prior;
        }
    }
    temp->data=data;
    return 0;
}

//9.删除双向链表中的指定数据 data代表删除所有出现的data数据
int deleteDataDoubleLinkList(double_list_t p, datatype data)
{
    link_list_t pdel=NULL;
    link_list_t q=p->head->next;
    while(p!=NULL)
    {
        if(p->head->data==data)
        {
            if(q==p->tail)//尾删
            {
                p->tail=p->tail->prior;
                free(p->tail->next);
                p->tail->next=NULL;
                q=NULL;
            }
            else//中间删
            {
                q->prior->next=q->next;
                q->next->prior=q->prior;
                pdel=q;
                free(pdel);
                pdel=NULL;
            }
            p->len--;
        }
        else{

            q=q->next;
        }
    }
     return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值