单链表与双链表的结构笔记

本文详细介绍了链表的基本使用、带头和不带头插入的区别,涵盖了头插法和尾插法创建单链表和双链表的方法,以及循环链表的实现。通过实例代码演示了如何在实际编程中运用这些技术。

通过代码的探索,了解链表基本的使用方法,以及带头插入和不带头插入,头插法和尾插法的区别

#include <iostream>
#include <malloc.h>
using namespace std;
//链表结构 
typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList; 

//双链表结构 
typedef struct DNode{
	int data;
	struct DNode *next,*prior;
}DNode,*DLinkList; 
//创建一个带头节点的单链表(头插法)
LinkList FrontLinkListWithHead(LinkList &L){
	LNode *s;int x;
	L = (LinkList)malloc(sizeof(LNode));
	L->data = -1;
	L->next = NULL;
	while(true){
		scanf("%d",&x);
		if(x==2022)break;
		s = (LNode *)malloc(sizeof(LNode));
		s->next = L->next;
		s->data = x;
		L->next = s;
	}
	return L;
} 
//创建一个不带头节点的单链表(头插法)
LinkList FrontLinkListWithoutHead(LinkList &L){
	LNode *s;int x;
	L = (LinkList)malloc(sizeof(LNode));
	scanf("%d",&x);
//注意退出情况
    if(x==2022)return NULL;
	L->data = x;
	L->next = NULL;
	while(true){
		scanf("%d",&x);
		if(x==2022)break;
		s = (LNode *)malloc(sizeof(LNode));
		s->next = L;
		s->data = x;
		L = s;
	}
	return s;
} 
//创建一个带头节点的单链表(尾插法)
LinkList BackLinkListWithHead(LinkList &L){
	LNode *s,*p;int x;
	L = (LinkList)malloc(sizeof(LNode));
	L->data = -1;
	L->next = NULL;
	p = L;
	while(true){
		scanf("%d",&x);
		if(x==2022)break;
		s = (LNode *)malloc(sizeof(LNode));
		s->next = NULL;
		s->data = x;
		p->next = s;
		p = s;
	}
	return L;
} 

//创建一个不带头节点的单链表(尾插法)
LinkList BackLinkListWithoutHead(LinkList &L){
	LNode *s,*p;int x;
	L = (LinkList)malloc(sizeof(LNode));
	scanf("%d",&x);
//注意退出情况
    if(x==2022)return NULL;
	L->data = x;
	L->next = NULL;
	p=L;
	while(true){
		scanf("%d",&x);
		if(x==2022)break;
		s = (LNode *)malloc(sizeof(LNode));
		s->next = NULL;
		s->data = x;
		p->next = s;
		p = s;
	}
	return L;
} 

//删除单链表中指定位置的元素(不算头节点的情况) 
void deletelinklist(LinkList &L,int i){
	LNode *p=L->next,*a;int k=1;
	while(++k<i-1 && p){ 
		p = p->next;
	}
	a = p->next;
	p->next = p->next->next;
	free(a);
} 

//创建一个带头节点的双链表(头插法)
DLinkList FrontDLinkListWithHead(DLinkList &L){
	 DNode *s; int x;
	 L = (DLinkList)malloc(sizeof(DNode));
	 L->data = -1;
	 L->prior = NULL;
	 L->next = NULL;
	 while(true){
	 	scanf("%d",&x);
	 	if(x==2022)break;
	 	s = (DNode *)malloc(sizeof(DNode));
	 	s->data = x;
	 	s->next = L->next;
	 	s->prior = L;
	 	if(L->next!=NULL){
	 		L->next->prior = s;
		}
		L->next = s; 
	 }
	 return L;
} 

//创建一个不带头节点的双链表(头插法)
DLinkList FrontDLinkListWithoutHead(DLinkList &L){
	 DNode *s; int x;
	 L = (DLinkList)malloc(sizeof(DNode));
	 scanf("%d",&x);
//注意退出情况
    if(x==2022)return NULL;
	 L->data = x;
	 L->prior = NULL;
	 L->next = NULL;
	 while(true){
	 	scanf("%d",&x);
	 	if(x==2022)break;
	 	s = (DNode *)malloc(sizeof(DNode));
	 	s->data = x;
	 	s->next = L;
	 	s->prior = NULL;
	 	L = s;
	 }
	 return s;
}

//创建一个带头节点的双链表(尾插法)
DLinkList BackDLinkListWithHead(DLinkList &L){
	DNode *s,*p;int x;
	L = (DLinkList)malloc(sizeof(DNode));
	L->data = -1;
	L->next = NULL;
	L->prior = NULL;
	p=L;
	while(true){
		scanf("%d",&x);
		if(x==2022)break;
		s = (DNode *)malloc(sizeof(DNode));
		s->next = NULL;
		s->prior = p;
		s->data = x;
		p->next = s;
		p = s;
	}
	return L;
} 

//创建一个不带头节点的双链表(尾插法)
DLinkList BackDLinkListWithoutHead(DLinkList &L){
	DNode *s,*p;int x;
	L = (DLinkList)malloc(sizeof(DNode));
	scanf("%d",&x);
//注意退出情况
    if(x==2022)return NULL;
	L->data = x;
	L->next = NULL;
	L->prior = NULL;
	p=L;
	while(true){
		scanf("%d",&x);
		if(x==2022)break;
		s = (DNode *)malloc(sizeof(DNode));
		s->next = NULL;
		s->prior = p;
		s->data = x;
		p->next = s;
		p = s;
	}
	return L;
} 

//打印单链表数据 
void printLinkList(LinkList L){
	while(L){
		if(L->data == -1){
			L = L->next;
			printf("本链表含有头节点:");
			continue; 
		}
		printf("%d,",L->data);
		L = L->next;
	}
} 

//打印双链表数据 
void printDLinkList(DLinkList L){
	while(L){
		if(L->data == -1){
			L = L->next;
			printf("本链表含有头节点:");
			continue; 
		}
		printf("%d,",L->data);
		L = L->next;
	}
} 

//删除双链表中指定位置的元素(不算头节点的情况) 
void deleteDlinklist(DLinkList &L,int i){
	DNode *p=L->next,*a;int k=1;
	while(++k<i-1 && p){ 
		p = p->next;
	}
	a = p->next;
	p->next->next->prior = p; 
	p->next = p->next->next;
	free(a);
}

//创建一个带头节点的循环单链表(头插法)
LinkList FrontCycleLinkListWithHead(LinkList &L){
	//初始化节点s暂存新节点,x为暂存值 
	LNode *s;int x; 
	//空间开辟 
	L = (LinkList)malloc(sizeof(LNode));
	//头节点建立,值为-1代表空 
	L->data = -1;
	//循环单链表,头部指向自己 
	L->next = L;
	//循环创建元素 
	while(true){
		//检测输入 
		scanf("%d",&x);
		//终止操作 
		if(x==2022)break;
		//新节点开辟空间 
		s = (LNode *)malloc(sizeof(LNode));
		//新节点继承后继节点 
		s->next = L->next;
		//新节点赋值 
		s->data = x;
		//头节点指向新节点 
		L->next = s;
	}
	//返回新链表的首地址 
	return L;
} 
//创建一个不带头节点的循环单链表(头插法)
LinkList FrontCycleLinkListWithoutHead(LinkList &L){
	//初始化节点s暂存新节点,x为暂存值 
	LNode *s;int x;
	//空间开辟 
	L = (LinkList)malloc(sizeof(LNode));
	//首元节点建立,值用户自定义 
	scanf("%d",&x);
	//空链表操作 
    if(x==2022)return NULL;
    //首元节点赋值 
	L->data = x;
	L->next = NULL;
	//循环创建链表 
	while(true){
		//检测输入 
		scanf("%d",&x);
		//终止操作 
		if(x==2022)break;
		//新节点开辟空间 
		s = (LNode *)malloc(sizeof(LNode));
		//新节点继承后继节点 
		s->next = L;
		//新节点赋值 
		s->data = x;
		//头节点指向新节点 
		L = s;
	}
	//返回新链表的首地址 
	return s;
} 

//创建一个带头节点的循环单链表(尾插法)
LinkList BackCycleLinkListWithHead(LinkList &L){
	//初始化暂存节点s 尾节点指针p(前驱节点) 暂存变量x 
	LNode *s,*p;int x;
	//空间开辟 
	L = (LinkList)malloc(sizeof(LNode));
	//节点赋值 
	L->data = -1;
	L->next = NULL;
	//尾节点指向头节点 
	p = L;
	//循环创建链表 
	while(true){
		//输入值 
		scanf("%d",&x);
		//检测终止操作 
		if(x==2022)break;
		//新节点开辟空间 
		s = (LNode *)malloc(sizeof(LNode));
		//新节点是尾插,后面节点为空 
		s->next = NULL;
		//新节点赋值 
		s->data = x;
		//前驱节点链接新节点 
		p->next = s;
		//前驱更新成当前节点 
		p = s;
	}
	//前驱节点指向头节点,构成循环链表 
	p->next = L; 
	//返回头节点地址 
	return L;
} 

//创建一个不带头节点的单链表(尾插法)
LinkList BackCycleLinkListWithoutHead(LinkList &L){
	//初始化暂存节点s 尾节点指针p(前驱节点) 暂存变量x 
	LNode *s,*p;int x;
	//空间开辟 
	L = (LinkList)malloc(sizeof(LNode));
	//输入x的值 
	scanf("%d",&x);
	//终止操作 
	if(x==2022)return NULL; 
	//首元节点赋值 
	L->data = x;
	L->next = NULL;
	//前驱节点更新为首元节点 
	p=L;
	//遍历插入链表 
	while(true){
		//输入X 
		scanf("%d",&x);
		//检测到特定值终止 
		if(x==2022)break;
		//空间开辟 
		s = (LNode *)malloc(sizeof(LNode));
		//新节点是尾插,后面节点为空 
		s->next = NULL;
		//新节点赋值 
		s->data = x;
		//前驱节点链接新节点 
		p->next = s;
		//前驱更新成当前节点 
		p = s;
	}
	//前驱节点指向首元节点,构成循环链表 
	p->next = L; 
	//返回头节点地址 
	return L;
} 

int main(){
	//单链表的测试数据 
	LinkList L;
	L = FrontLinkListWithoutHead(L);
	printLinkList(L);
	printf("\n");
	deletelinklist(L,3);
	printLinkList(L);
	printf("双链表测试开始\n"); 
    //双链表的测试数据
	DLinkList L1;
	L1 = BackDLinkListWithHead(L1);
	deleteDlinklist(L1,3);
	printDLinkList(L1); 
	return 0; 
}

总结:带头插入与不带头插入的区别取决于第一个结点是否含有有效的数据,同时需要注意的是头插法与尾插法是否含有头节点的代码区别。头插法节点区别较大,以下为您展开讲解。

头插法:

当您使用头插法含有头节点时,您只需在头节点后面挂载元素,并使新的元素指向后续的元素即可。

当您使用头插法不包含头节点时,将头节点视为一个指针,这个指针始终指向第一个含有元素的节点。当您继续添加元素时,这个指针在最后会更新指向此节点的数据,注意最后返回的新生成节点的地址。

以上代码仅供参考,如有错误请大家指正,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值