双向链表操作c语言 函数,双向链表的相关操作--C语言实现

/************************************************************************/

/* DList.h

双向链表相关操作函数头文件*/

/************************************************************************/

#ifndef __DList_H

#define __DList_H

typedef int Item;

typedef struct Node * PNode;

typedef PNode Position;

/*定义节点类型*/

typedef struct Node

{

Item data;/*数据域*/

PNode previous; /*指向前驱*/

PNode next;/*指向后继*/

}Node;

/*定义链表类型*/

typedef struct

{

PNode head;/*指向头节点*/

PNode tail;/*指向尾节点*/

int size;

}DList;

/*分配值为i的节点,并返回节点地址*/

Position MakeNode(Item i);

/*释放p所指的节点*/

void FreeNode(PNode p);

/*构造一个空的双向链表*/

DList* InitList();

/*摧毁一个双向链表*/

void DestroyList(DList *plist);

/*将一个链表置为空表,释放原链表节点空间*/

void ClearList(DList *plist);

/*返回头节点地址*/

Position GetHead(DList *plist);

/*返回尾节点地址*/

Position GetTail(DList *plist);

/*返回链表大小*/

int GetSize(DList *plist);

/*返回p的直接后继位置*/

Position GetNext(Position p);

/*返回p的直接前驱位置*/

Position GetPrevious(Position p);

/*将pnode所指节点插入第一个节点之前*/

PNode InsFirst(DList *plist,PNode pnode);

/*将链表第一个节点删除并返回其地址*/

PNode DelFirst(DList *plist);

/*获得节点的数据项*/

Item GetItem(Position p);

/*设置节点的数据项*/

void SetItem(Position p,Item i);

/*删除链表中的尾节点并返回其地址,改变链表的尾指针指向新的尾节点*/

PNode Remove(DList *plist);

/*在链表中p位置之前插入新节点S*/

PNode InsBefore(DList *plist,Position p,PNode s);

/*在链表中p位置之后插入新节点s*/

PNode InsAfter(DList *plist,Position p,PNode s);

/*返回在链表中第i个节点的位置*/

PNode LocatePos(DList *plist,int i);

/*依次对链表中每个元素调用函数visit()*/ //visit为函数指针

void ListTraverse(DList *plist,void (*visit)(Item));

/*对链表中的节点数据项进行打印*/

void print(Item i);

#endif

/************************************************************************/

/* DList.c

双向链表相关操作源文件*/

/************************************************************************/

#include "stdafx.h"

#include "DList.h"

#include

#include

/*分配值为i的节点,并返回节点地址*/

Position MakeNode(Item i)

{

PNode p = NULL;

p = (PNode)malloc(sizeof(Node));

if(p!=NULL)

{

p->data = i;

p->previous = NULL;

p->next = NULL;

}

return p;

}

/*释放p所指的节点空间*/

void FreeNode(PNode p)

{

free(p);

}

/*构造一个空的双向链表*/

DList * InitList()

{

DList *plist = (DList *)malloc(sizeof(DList));

PNode head = MakeNode(0);

if(plist!=NULL)

{

if(head!=NULL)

{

plist->head = head;

plist->tail = head;

plist->size = 0;

}

else

return NULL;

}

return plist;

}

/*摧毁一个双向链表*/

void DestroyList(DList *plist)

{

ClearList(plist);

free(GetHead(plist));

free(plist);

}

/*判断链表是否为空表*/

int IsEmpty(DList *plist)

{

if(GetSize(plist)==0 && GetTail(plist)==GetHead(plist))

return 1;

else

return 0;

}

/*将一个链表置为空表,释放原链表节点空间*/

void ClearList(DList *plist)

{

PNode temp,p;

p = GetTail(plist);

while(!IsEmpty(plist))

{

temp = GetPrevious(p);

FreeNode(p);            //释放p所指结点的空间

p = temp;

plist->tail = temp;

plist->size--;

}

}

/*返回头节点地址*/

Position GetHead(DList *plist)

{

return plist->head;

}

/*返回尾节点地址*/

Position GetTail(DList *plist)

{

return plist->tail;

}

/*返回链表大小*/

int GetSize(DList *plist)

{

return plist->size;

}

/*返回p的直接后继位置*/

Position GetNext(Position p)

{

return p->next;

}

/*返回p的直接前驱位置*/

Position GetPrevious(Position p)

{

return p->previous;

}

/*将pnode所指节点插入第一个节点之前*/

PNode InsFirst(DList *plist,PNode pnode)

{

Position head = GetHead(plist);

if(IsEmpty(plist))

plist->tail = pnode;    //双向链表为空,作为尾节点

pnode->next = head->next;

pnode->previous = head;

if(head->next!=NULL)

head->next->previous = pnode;

head->next = pnode;

plist->size++;

return pnode;

}

/*将链表第一个节点删除,返回该节点的地址*/

PNode DelFirst(DList *plist)

{

Position head = GetHead(plist);

Position p=head->next;

if(p!=NULL)

{

if(p==GetTail(plist))

plist->tail = p->previous; //若p为尾节点,则将p的前驱节点作为尾节点

head->next = p->next;

head->next->previous = head;

plist->size--;

}

return p;

}

/*获得节点的数据项*/

Item GetItem(Position p)

{

return p->data;

}

/*设置节点的数据项*/

void SetItem(Position p,Item i)

{

p->data = i;

}

/*删除链表中的尾节点并返回地址,改变链表的尾指针指向新的尾节点*/

PNode Remove(DList *plist)

{

Position p=NULL;

if(IsEmpty(plist))

return NULL;

else

{

p = GetTail(plist);

p->previous->next = p->next;

plist->tail = p->previous;

plist->size--;

return p;

}

}

/*在链表中p位置之前插入新节点s*/

PNode InsBefore(DList *plist,Position p,PNode s)

{

s->previous = p->previous;

s->next = p;

p->previous->next = s;

p->previous = s;

plist->size++;

return s;

}

/*在链表中p位置之后插入新节点s*/

PNode InsAfter(DList *plist,Position p,PNode s)

{

s->next = p->next;

s->previous = p;

if(p->next != NULL)                //判断位置p是否为头节点

p->next->previous = s;

p->next = s;

//if(p = GetTail(plist))         //old

if(p == GetTail(plist))            //new 判断位置p是否为尾节点

plist->tail = s;

plist->size++;

return s;

}

/*返回在链表中第i个节点的位置*/

PNode LocatePos(DList *plist,int i)

{

int cnt = 0;

Position p = GetHead(plist);

if(i>GetSize(plist) || i<1)

return NULL;

while(++cnt<=i)

{

p=p->next;

}

return p;

}

/*依次对链表中每个元素调用函数visit()*/

void ListTraverse(DList *plist,void (*visit)(Item))

{

Position p = GetHead(plist);

if(IsEmpty(plist))

exit(0);

else

{

while(p->next!=NULL)

{

p = p->next;

visit(p->data);

}

}

}

/*打印链表中节点的数据项*/

void print(Item i)

{

printf("数据项为%d \n",i);

}

int main()

{

printf("双向链表操作测试\n")

DList *plist = NULL;

PNode pn = NULL;

plist = InitList();

pn = InsFirst(plist,MakeNode(1));

InsBefore(plist,pn,MakeNode(2));

InsAfter(plist,pn,MakeNode(3));

printf("p前驱位置的值为%d\n",GetItem(GetPrevious(pn)));

printf("p位置的值为%d\n",GetItem(pn));

printf("p后继位置的值为%d\n",GetItem(GetNext(pn)));

printf("遍历输出各节点数据项:\n");

ListTraverse(plist,print);

printf("除了头节点该链表共有%d个节点\n",GetSize(plist));

FreeNode(DelFirst(plist));

printf("删除第一个节点后重新遍历输出为:\n");

ListTraverse(plist,print);

printf("除了头节点该链表共有%d个节点\n",GetSize(plist));

DestroyList(plist);

printf("链表已被销毁\n");

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
循环双向链表是一种链表结构,它可以在单链表的基础上,增加一个指向前一个结点的指针,从而实现双向遍历。循环双向链表是指尾结点的 next 指针指向头结点,头结点的 prev 指针指向尾结点,形成一个循环。 以下是循环双向链表的 C 语言实现: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node *prev; struct Node *next; } Node; Node *create_node(int data) { Node *new_node = (Node *)malloc(sizeof(Node)); new_node->data = data; new_node->prev = NULL; new_node->next = NULL; return new_node; } void insert_node(Node **head, Node *new_node) { if (*head == NULL) { *head = new_node; (*head)->prev = new_node; (*head)->next = new_node; } else { Node *tail = (*head)->prev; tail->next = new_node; new_node->prev = tail; new_node->next = *head; (*head)->prev = new_node; } } void delete_node(Node **head, Node *del_node) { if (*head == NULL || del_node == NULL) { return; } if (*head == del_node) { *head = del_node->next; } if (del_node->next != NULL) { del_node->next->prev = del_node->prev; } if (del_node->prev != NULL) { del_node->prev->next = del_node->next; } free(del_node); } void print_list(Node *head) { if (head == NULL) { printf("List is empty\n"); } else { Node *current = head; do { printf("%d ", current->data); current = current->next; } while (current != head); printf("\n"); } } int main() { Node *head = NULL; Node *node1 = create_node(1); Node *node2 = create_node(2); Node *node3 = create_node(3); insert_node(&head, node1); insert_node(&head, node2); insert_node(&head, node3); print_list(head); delete_node(&head, node2); print_list(head); return 0; } ``` 在上面的代码中,我们定义了一个 Node 结构体,表示循环双向链表的结点。create_node 函数用于创建一个新结点,insert_node 函数用于将新结点插入链表,delete_node 函数用于删除指定结点,print_list 函数用于打印链表。 在 main 函数中,我们创建了三个结点,然后插入链表,打印链表,删除第二个结点,再次打印链表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值