不带头节点的循环双链表

1.创建一个双链表的类型

复制代码
typedef struct DLNode
{
	int data;
	struct DLNode* prior, * next;//里面有两个指针,一个前驱指针,一个后驱指针
} DLNode, * DLinkList;//重新定义一个名字,DLNode是节点名字,DLinkList是双链条的名字,也是个指针

2.用创建好的结构体创建一个变量,进行初始化

复制代码
int InitDLinkList(DLinkList*L)
{
	(*L) = NULL;//把表头置为空
	return 0;
}

3.判断表是不是空表,因为有两个节点指针,判断节点指针是不是都为空即可

复制代码
int Is_empty(DLinkList*L)
{
	return((*L)->next == NULL) && ((*L)->prior == NULL);//只要两个节点都指向空说明这个链表没有数据
}

4.给定一个位序进行插入,因为不带头节点所以考虑的事情相对多,要考虑第一个元素可最后一个元素

复制代码
int insertLocate(DLinkList* L, int i, int elem)//在位序为i处插入一个elem 的元素
{
	if (i < 0)
	{
		return 1;
	}
	if (i == 1)
	{
		DLNode* s = (DLNode*)malloc(sizeof(DLNode));
		if (s == NULL)
		{
			return 1;
		}
		s->data = elem;
		s->next = NULL;
		s->prior = NULL;
		(*L) = s;
		return 0;
	}
	int j = 1;
	DLNode* p = (*L);//将第一个元素付给p节点,就一个节点这个节点就是p
	while (p != NULL && j < i - 1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
		return 1;//i的值不合法
	}
	DLNode* q = (DLNode*)malloc(sizeof(DLNode));
	if (q == NULL)
	{
		return 1;
	}
	q->data = elem;
	q->next = p->next;
	if(p->next!=NULL)//如果等于就只需要链接三条线因为最后一个元素没有前驱指针
	p->next->prior = q;
	p->next = q;
	q->prior = p;
	return 0;
}

5.给定一个节点进行插入操作

复制代码
int InsertDLNode(DLinkList* L, DLNode* p,DLNode*s, int elem)//在指定的节点p插入一个数据元素为elem的数据
{
	if (p == NULL)
	{
		return 1;
   }
	s->next = p->next;//插入到p节点的后面,然后交换p指针和q指针的值
	if(p->next!=NULL)
	p->next->prior = s;
	p->next = s;
	s->prior = p;
	s->data = p->data;
	p->data = elem;
	return 0;
}

6.给定一个值,查找这个值的位序

复制代码
int GetLocate(DLinkList* L, int elem)//查找elem的位序
{
	DLNode* p = (*L);
	int count = 0;
	while (p)
	{
		count++;
		if (p->data == elem)
		{
			return count;//返回位序
		}
		p = p->next;
	}
	return -1;//找不到返回-1

7.给定一个值,删除第一个相同的值

复制代码
nt DeleteElem(DLinkList* L, int elem)
{
	if ((*L)->data == elem)
	{
		DLNode* p = (*L)->next;
		(*L)->next->prior = (*L)->prior;
		free(*L);
		(*L) = p;
	}
	int pos=GetLocate(L, elem);//pos=位序
	int j = 1;
	DLNode* p = (*L);
	while (p != NULL && j < pos - 1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
		return 0;
	}
	DLNode* ptr = p->next;
	p->next = ptr->next;
	if (ptr->next != NULL)
	ptr->next->prior = p;
	free(ptr);
}

8.打印整个链表的数据

复制代码
void Display(DLinkList* L)
{
	DLNode* p = (*L);
	while (p!=NULL)//如果p等于NULL说明这个时候就是错误的,不会进入循环里面
	{
		printf("%d-> ", p->data);
		p = p->next;
	}
	printf("NULL\n");
}

9.头插法建立双链表,头插法很重要,链表的逆置需要用到头插法

复制代码
int HeadInsert(DLinkList* L)//头插法建立单链表
{
	int x = 0;
	scanf("%d", &x);
	DLNode* s = (DLNode*)malloc(sizeof(DLNode));
	if (s == NULL)
	{
		return 1;
	}
	s->data = x;
	s->next = NULL;
	s->prior = NULL;//头插法建立双链表的时候先整一个头节点,逻辑上的头节点
	(*L) = s;
	scanf("%d", &x);
	while (x)//x为零就结束建立
	{
		DLNode* s = (DLNode*)malloc(sizeof(DLNode));
		if (s == NULL)
		{
			return 1;
		}
		s->next = (*L);
		(*L)->prior = s;
		s->data = x;
		(*L) = s;
		scanf("%d", &x);
	}
	return 0;
}

10.尾插法建立单链表

复制代码
int TailInsert(DLinkList* L)
{
	int x = 0;
	scanf("%d", &x);
	DLNode* s = (DLNode*)malloc(sizeof(DLNode));
	if (s == NULL)
	{
		return 1;
	}
	s->data = x;
	s->next = NULL;
	s->prior = NULL;
	(*L) = s;
	//(*L)->next = NULL;
	scanf("%d", &x);
	DLNode* tail = (*L);//把头节点赋值个头指针
	while (x)
	{
		DLNode* s = (DLNode*)malloc(sizeof(DLNode));
		if (s == NULL)
		{
			return 1;
		}
		s->data = x;
		tail->next = s->next;
		s->prior = tail;
		tail->next = s;
		tail = s;
		scanf("%d", &x);
	}
	tail->next = NULL;//最后要把尾指针置为NULL
	return 0;
}

11.总体代码

复制代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
typedef struct DLNode
{
	int data;
	struct DLNode* prior, * next;//里面有两个指针,一个前驱指针,一个后驱指针
} DLNode, * DLinkList;//重新定义一个名字,DLNode是节点名字,DLinkList是双链条的名字,也是个指针

int InitDLinkList(DLinkList*L)
{
	(*L) = NULL;//把表头置为空
	return 0;
}
int Is_empty(DLinkList*L)
{
	return((*L)->next == NULL) && ((*L)->prior == NULL);//只要两个节点都指向空说明这个链表没有数据
}
int InsertDLNode(DLinkList* L, DLNode* p,DLNode*s, int elem)//在指定的节点p插入一个数据元素为elem的数据
{
	if (p == NULL)
	{
		return 1;
   }
	s->next = p->next;//插入到p节点的后面,然后交换p指针和q指针的值
	if(p->next!=NULL)
	p->next->prior = s;
	p->next = s;
	s->prior = p;
	s->data = p->data;
	p->data = elem;
	return 0;
}
int insertLocate(DLinkList* L, int i, int elem)//在位序为i处插入一个elem 的元素
{
	if (i < 0)
	{
		return 1;
	}
	if (i == 1)
	{
		DLNode* s = (DLNode*)malloc(sizeof(DLNode));
		if (s == NULL)
		{
			return 1;
		}
		s->data = elem;
		s->next = NULL;
		s->prior = NULL;
		(*L) = s;
		return 0;
	}
	int j = 1;
	DLNode* p = (*L);//将第一个元素付给p节点,就一个节点这个节点就是p
	while (p != NULL && j < i - 1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
		return 1;//i的值不合法
	}
	DLNode* q = (DLNode*)malloc(sizeof(DLNode));
	if (q == NULL)
	{
		return 1;
	}
	q->data = elem;
	q->next = p->next;
	if(p->next!=NULL)//如果等于就只需要链接三条线因为最后一个元素没有前驱指针
	p->next->prior = q;
	p->next = q;
	q->prior = p;
	return 0;
}
int GetLocate(DLinkList* L, int elem)//查找elem的位序
{
	DLNode* p = (*L);
	int count = 0;
	while (p)
	{
		count++;
		if (p->data == elem)
		{
			return count;//返回位序
		}
		p = p->next;
	}
	return -1;//找不到返回-1
}
int DeleteElem(DLinkList* L, int elem)
{
	if ((*L)->data == elem)
	{
		DLNode* p = (*L)->next;
		(*L)->next->prior = (*L)->prior;
		free(*L);
		(*L) = p;
	}
	int pos=GetLocate(L, elem);//pos=位序
	int j = 1;
	DLNode* p = (*L);
	while (p != NULL && j < pos - 1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
		return 0;
	}
	DLNode* ptr = p->next;
	p->next = ptr->next;
	if (ptr->next != NULL)
	ptr->next->prior = p;
	free(ptr);
}
void Display(DLinkList* L)
{
	DLNode* p = (*L);
	while (p!=NULL)//如果p等于NULL说明这个时候就是错误的,不会进入循环里面
	{
		printf("%d-> ", p->data);
		p = p->next;
	}
	printf("NULL\n");
}

int HeadInsert(DLinkList* L)//头插法建立单链表
{
	int x = 0;
	scanf("%d", &x);
	DLNode* s = (DLNode*)malloc(sizeof(DLNode));
	if (s == NULL)
	{
		return 1;
	}
	s->data = x;
	s->next = NULL;
	s->prior = NULL;//头插法建立双链表的时候先整一个头节点,逻辑上的头节点
	(*L) = s;
	scanf("%d", &x);
	while (x)//x为零就结束建立
	{
		DLNode* s = (DLNode*)malloc(sizeof(DLNode));
		if (s == NULL)
		{
			return 1;
		}
		s->next = (*L);
		(*L)->prior = s;
		s->data = x;
		(*L) = s;
		scanf("%d", &x);
	}
	return 0;
}

int TailInsert(DLinkList* L)
{
	int x = 0;
	scanf("%d", &x);
	DLNode* s = (DLNode*)malloc(sizeof(DLNode));
	if (s == NULL)
	{
		return 1;
	}
	s->data = x;
	s->next = NULL;
	s->prior = NULL;
	(*L) = s;
	//(*L)->next = NULL;
	scanf("%d", &x);
	DLNode* tail = (*L);//把头节点赋值个头指针
	while (x)
	{
		DLNode* s = (DLNode*)malloc(sizeof(DLNode));
		if (s == NULL)
		{
			return 1;
		}
		s->data = x;
		tail->next = s->next;
		s->prior = tail;
		tail->next = s;
		tail = s;
		scanf("%d", &x);
	}
	tail->next = NULL;//最后要把尾指针置为NULL
	return 0;
}
int main()
{
	DLinkList L;
	InitDLinkList(&L);
	/*insertLocate(&L, 1, 2);
	insertLocate(&L, 2, 3);
	insertLocate(&L, 3, 4);
	insertLocate(&L, 4, 5);
	insertLocate(&L, 5, 6);*/
	TailInsert(&L);
	//insertLocate(&L, 6, 7);

	//DeleteElem(&L,7);
	//DeleteElem(&L, 7);

	int ret=Is_empty(&L);
	if (ret)
	{
		printf("空\n");
	}
	else
	{
		printf("非空\n");
	}
	Display(&L);

	int pos = GetLocate(&L, 6);
	printf("%d\n",pos);//
	return 0;
}
相关推荐
潜创微科技--高清音视频芯片方案开发17 小时前
2026年C转DP芯片方案深度分析:从适配场景到成本性能的优选指南
c语言·开发语言
青桔柠薯片18 小时前
从C语言到裸机运行:i.MX6ULL 的 GPIO 控制与编译链接过程分析
c语言·开发语言·imx6ull
xiaobobo333018 小时前
c语言结构体相关箭头运算符和点号运算符的联系以及c语言的“索引”思想
c语言·箭头运算符·点号运算符·索引思想
weixin_5375904519 小时前
《C程序设计语言》练习答案(练习1-13)
c语言·开发语言·c#
always_TT19 小时前
从Python_Java转学C语言需要注意什么?
java·c语言·python
DA022120 小时前
Linux驱动-I2C总线驱动
linux·c语言·linux驱动
always_TT21 小时前
C语言保留字与标识符规则
c语言·开发语言
AI科技星1 天前
光速螺旋量子几何统一场论——基于 v ≡ c 公理的四大基本力全维度求导证明与精准数值验证
c语言·开发语言·人工智能·算法·机器学习·平面
程序猿编码1 天前
隐匿注入型ELF加壳器:原理、设计与实现深度解析(C/C++ 代码实现)
c语言·网络·c++·elf·代码注入
爱编码的小八嘎1 天前
C语言完美演绎6-4
c语言