【数据结构】双向链表

(近期我在学习数据结构,于是我自己整理了单链表、循环单链表、双向链表、双向循环链表的相关代码,以巩固这段时间的学习,也希望能够帮助初学者,希望大家在阅读以下代码时发现问题纠正于我,一起探讨)

DoubleList.h

#ifndef __DOUBLELIST_H
#define __DOUBLELIST_H

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>

typedef int ElemType;

//定义每一个结点的结构
typedef struct Node
{
	struct Node *prev; //每个结点的前驱
	ElemType data;     //结点的值
	struct Node *next; //每个结点的后继	
}Node;

//定义双向链表结构
typedef struct Doublelist
{
	Node head;  //头结点
	int count;  //记录一个双向链表的结点的数目
}Doublelist, *pDoulist;

//初始化链表函数
void InitDoublelist(pDoulist list); 
   
//插入节点函数
void InsertDoublelist(pDoulist list, ElemType val , int pos);

//头插函数
void  InsertHeadDoublelist (pDoulist list,ElemType val);

//尾插函数
void InsertTailDoublelist(pDoulist list,ElemType val);

//删除结点函数
void DeleteDoublelist(pDoulist list,int pos);

//删除头结点的函数
void DeleteHeadDoublelist(pDoulist list);

//删除尾结点的函数
void DeleteTailDoublelist(pDoulist list);

//销毁链表函数
void DestroyDoublelist(pDoulist list);

//顺序输出结点数据函数1
void Show1(pDoulist list);

//顺序输出结点数据函数2
void Show2(pDoulist list);

//逆序输出结点数据函数
void Reverseshow(pDoulist list);

#endif

DoubleList.c

#include"DoubleList.h"

//初始化双向链表
void InitDoublelist(pDoulist list)
{
	assert(list != NULL);

	list->head.next  = NULL;   //初始化尾指针
	list->head.prev  = NULL;   //初始化头指针
	list->count = 0;           //初始化结点个数i

}

//在双向链表中插入一个结点
	//1:先考虑普通情况下的结点插入
/*
void InsertDoublelist(pDoulist list, ElemType val, int pos)
{
	assert(list != NULL);
	if( pos < 0 | pos > list->count )
	{
		printf("pos is error\n");
		return ;
	}
	Node *p = &list->head;
	Node *s = ( Node *)malloc(sizeof(Node));
	while( pos > 0)
	{
		p = p->next;
		pos--;
	}
	s->data = val;
	if( p->next != NULL)
	{
		p->next->prev = s;
	}
	s->next = p->next;
	s->prev = p;
	p->next = s;
	list->count++;
}
*/
	//2:考虑特殊情况的结点插入优化代码(list->count == 0  和 pos == list->count )
static Node *BuyNode(ElemType val, Node *prev, Node *next )//购买结点
{
	Node *s = (Node *)malloc(sizeof(Node));
	assert( s != NULL);

	s->data = val;
	s->prev = prev;
	s->next = next;

	return s;
}
void InsertDoublelist(pDoulist list, ElemType val, int pos)
{
	assert( list != NULL);
	if( (pos < 0) || (pos > list->count))
	{
		printf("pos is error\n");
		return ;
	}
	Node *p = &list->head;
	while( pos > 0)
	{
		p = p->next;
		pos --;
	}
	Node *s = BuyNode( val, p, p->next);//插入结点
	if( p->next != NULL)//考虑尾插
	{
		p->next->prev = s;
	}
	p->next = s;
	list->count++;
}

//头插函数
void  InsertHeadDoublelist (pDoulist list,ElemType val)
{
	InsertDoublelist(list, val, 0);//头插函数可以调用插入函数,将插入函数的pos参数设置为0
}

//尾插函数
void InsertTailDoublelist(pDoulist list,ElemType val)
{
	InsertDoublelist(list, val, list->count);//尾插函数可以调用插入函数,将插入函数的pos参数设置为list->count
}

//删除双向链表中的一个结点
void DeleteDoublelist(pDoulist list,int pos)
{
	assert(list != NULL);
	if((pos < 1) ||(pos > list->count))
	{
		printf("pos is error\n");
		return ;
	}
	Node * p = &list->head;
	while( pos > 0)
	{
		p = p->next;
		pos --;
	}
	p->prev->next = p->next;
	if ( p->next != NULL)
	{
		p->next->prev = p->prev;
	}
	free(p);
	list->count--;
}

//删除头结点的函数
void DeleteHeadDoublelist(pDoulist list)
{
	DeleteDoublelist(list,1);//头结点的删除可以调用删除函数,将删除函数的pos参数设置为1
}

//删除尾结点的函数
void DeleteTailDoublelist(pDoulist list)
{
	DeleteDoublelist(list,list->count);//尾结点的删除可以调用删除函数,将删除函数的pos参数设置为list->count
}

//输出双向链表中的数据1
void Show1(pDoulist list)
{
	assert(list != NULL);
	Node *p = list->head.next;
	while( p != NULL)//用指针遍历整个链表,指针跑一个输出一个
	{
		printf("%3d",p->data);
		p = p->next;
	}
	printf("\n");
}

void Show2(pDoulist list)
{
	assert( list != NULL);
	Node *p = list->head.next;
	int tmp = list->count;
	while( tmp > 0)
	{
		printf("%3d",p->data);
		p = p->next;
		tmp --;
	}
	printf("\n");	
}

//逆序输出双向链表中的数据
void Reverseshow(pDoulist list)
{
	assert( list != NULL);
	Node *p = &list->head;
	while( p->next != NULL)//先让指针跑到最后一个结点
	{
		p = p->next;
	}
	while( p->prev != NULL)//指针开始往前跑,指针跑一个输出一个值
	{
		printf("%3d",p->data);
		p = p->prev;
	}
	printf("\n");
}
//销毁一个双向链表
void DestroyDoublelist(pDoulist list)
{
	assert(list != NULL);
	while( list->count > 0)
	{
		DeleteHeadDoublelist(list); //调用删除头结点的函数,采用循环的方式每次删除头结点
	}
}

(测试)main.c

#include"DoubleList.h"

int main()
{
	Doublelist list;
	Doublelist *p = &list;
	InitDoublelist(&list); //初始化链表 

	printf("count3 =  %d\n",p->count);
	for( int i = 0; i < 5; i++ )
	{
		InsertDoublelist(&list,i * 10 ,i);  //插入节点函数
		Show1(&list);//顺序输出结点数据函数
	}
	Show1(&list);//顺序输出结点数据函数

	InsertTailDoublelist(&list,88);
	InsertHeadDoublelist (&list,99);
	Show2(&list);
	Reverseshow(&list);//逆序输出结点数据函数

	for( int i = 4; i > 0; i--)//删除前四个结点
	{
		DeleteDoublelist(&list,i);//删除结点函数
		Show2(&list);//顺序输出结点数据函数
	}
	Show2(&list);//顺序输出结点数据函数
	return 0;
}



输出结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值