Day03_数据结构(顺序结构&单向链表&单向循环链表&双向链表&双向循环链表)

发布于:2025-06-22 ⋅ 阅读:(14) ⋅ 点赞:(0)

01.顺序结构

main.c

#include "seq.h"
int main(){
	
	seq_p S=create_seqlist();
	inputall(S);
	insert_head(S);
	delete_head(S);
	insert_tail(S);
	delete_tail(S);
	insert_pos(S);
	delete_pos(S);
	update(S);
	int ret=findpos(S);
	printf("主函数输出查找后的列表%d\n",ret);
	seq_free(&S);
	output(S);
	return 0;
}

seq.c

#include "seq.h"
seq_p create_seqlist()
{
	seq_p S=(seq_p)malloc(sizeof(seq_list));
	if(S==NULL){
		return NULL;
	}
	bzero(S,sizeof(seq_list));
	return S;

}
int empty_seq(seq_p S)
{
	if(S==NULL){
		printf("入参为空\n");
		return -2;
	}
	return S->len==0?1:0;
}
int full_seq(seq_p S)
{
	if(S==NULL){
		printf("入参为空\n");
		return -2;
	}
	return S->len==MAX?1:0;

}
//输出数据函数
void output(seq_p S)
{
	if(S==NULL){return;}
	int n=empty_seq(S);
	if(n==1){
		printf("02:顺序列表为空,没有数据可以删除\n");
		return;
	}
	int i;
	for(i=0;i<S->len;++i){
		printf("%d ",S->arr[i]);
	}
	puts("");
	
}
//输入数据函数
seq_p input(seq_p S)
{
	printf("请输入您需要插入的数据:");
	scanf("%d",&S->number);
	return S;
}
//先插入数据中的顺序列表
seq_p inputall(seq_p S)
{
	printf("请输入您要放入空列表中的个数:");
	scanf("%d",&S->num1);
	printf("请输入数据:");
	getchar();
	for(int i=0;i<S->num1;++i){
		scanf("%d",&S->arr[i]);
		S->len++;
	}
	return S;
}

//头插
seq_p insert_head(seq_p S)
{ 	
	if(S==NULL){return NULL;}
	int m=full_seq(S);
	if(m==1){
		printf("01:顺序列表已满,不能插入数据\n");
		output(S);
		return S;
	}else if(m==0){
		input(S);
		int i;
		for(i=S->len-1;i>=0;--i){
			S->arr[i+1]=S->arr[i];
		}
		S->arr[0]=S->number;
		S->len++;
		printf("01:输出插入头部数据的顺序列表:\n");
		output(S);
		return S;
	}

}
//头删
seq_p delete_head(seq_p S)
{
	if(S==NULL){return NULL;}
	int n=empty_seq(S);
	if(n==1){
		printf("02:顺序列表为空,没有数据可以删除\n");
		return S;
	}else if(n==0){

		for(int i=1;i<S->len;++i){
			S->arr[i-1]=S->arr[i];
		}
		S->len=S->len-1;
		printf("02:输出删除头部数据的顺序列表\n");
		output(S);
		return S;
	}

}
//尾插
seq_p insert_tail(seq_p S)
{
   if(S==NULL){return NULL;}
   int m=full_seq(S);  
	if(m==1){
		printf("03:顺序列表已满,不能插入尾部数据\n");
		output(S);
		return S;
	}else if(m==0){
		input(S);
		S->arr[S->len]=S->number;
		S->len++;
		printf("03:输出插入尾部数据的顺序列表\n");
		output(S);
		return S;
	}

}
//尾删
seq_p delete_tail(seq_p S)
{
    if(S==NULL){return NULL;}
	int n=empty_seq(S);
	if(n==1){
		printf("04:顺序列表为空,尾部没有数据可以删除\n");
		return S;
	}else if(n==0){
		S->arr[S->len]=0;
		S->len=S->len-1;
		printf("04:输出删除尾部数据的顺序列表:\n");
		output(S);
		return S;
	}

}
seq_p insert_pos(seq_p S)
{
	if(S==NULL){return NULL;}
	int m=full_seq(S);
	if(m==1){
		printf("05:顺序列表已满,不能插入按位置插入数据\n");
		output(S);
		return S;
	}else if(m==0){
		int number,pos;
		printf("05:请输入您需要插入的数据和位置:");
		scanf("%d%d",&number,&pos);
		if(pos<0||pos>S->len){
			printf("位置不合理.\n");
			return S;
		}
		int i;
		for(i=S->len-1;i>=pos;--i){
			S->arr[i+1]=S->arr[i];
		}
		S->arr[pos]=number;
		S->len++;

			
		printf("05:输出按位置插入数据的顺序列表:\n");
		output(S);
		return S;
	}
}
seq_p delete_pos(seq_p S)
{
	if(S==NULL){return NULL;}
	int n=empty_seq(S);
	if(n==1){
		printf("06:顺序列表为空,不能删除按位置插入数据\n");
		output(S);
		return S;
	}else if(n==0){
		int number,pos;
		printf("06:请输入您需要删除的数据和位置:");
		scanf("%d%d",&number,&pos);
		if(pos<0||pos>=S->len)
		{
			printf("位置不合理\n");
		}
		int i;
		for(i=pos+1;i<=S->len;++i){
			S->arr[i-1]=S->arr[i];
		}
		S->len--;
		printf("06:输出按位置删除数据的顺序列表:\n");
		output(S);
		return S;
	}

	

}

//12.按位置修改元素
seq_p update(seq_p S)
{	
	if(S==NULL){return NULL;}
	int n=empty_seq(S);
	if(n==1){
		printf("12:顺序列表为空,不能按位置修改数据\n");
		output(S);
		return S;
	}else if(n==0){
		int number,pos;
		printf("12:请输入您需要修改的位置和数据:");
		scanf("%d%d",&number,&pos);
		if(pos<0||pos>=S->len)
		{
			printf("位置不合理\n");
		}
		S->arr[pos-1]=number;		
		printf("12:输出按位置修改数据的顺序列表:\n");
		output(S);
		return S;
	}

}
//13.按值查找返回下标
int findpos(seq_p S)
{
	if(S==NULL){return -1;}
	int n=empty_seq(S);
	if(n==1){
		printf("13:顺序列表为空,不能按数据查找下标\n");
		output(S);
		return -1;
	}else if(n==0){
		int number,pos;
		printf("13:请输入您需要查找的数据");
		scanf("%d",&number);
		for(int i=0;i<S->len;++i){
			if(S->arr[i]==number){
				pos=i;
				printf("13_01:查找数据%d存在顺序列表中下标%d\n",number,pos);	
				printf("13_02:输出查找后数据的顺序列表:\n");
				output(S);
				return pos;
			}
		}	
		printf("13_03:查找数据%d不存在顺序列表中\n",number);
		return -2;
		printf("13_04:输出查找后数据的顺序列表:\n");
		output(S);
		
	}
}

//释放顺序表
# if 0
void seq_free(seq_p S)
{

	printf("释放顺序列表前数据:\n");
	output(S);
	if(S!=NULL){
		free(S);	
	}
	printf("%p\n",S);
	return;
}
#endif 
#if 1
void seq_free(seq_p *S)
{
	printf("100:释放顺序列表前数据:\n");
	output(*S);
	//必须先判断S的值,再判断*S的值
	if(S==NULL||*S==NULL)
	{
		printf("入参不合理\n");
		return;
	}
	free(*S);
	*S=NULL;
	printf("100:释放顺序列表后数据\n");
	
	printf("%p\n",S);
	return;
}
#endif 

seq.h

#ifndef __SEQ_H__
#define __SEQ_H__
#include <stdio.h>                     
#include <string.h>                    
#include <stdlib.h> 
#define MAX 6
typedef struct seq_list
{
	int arr[MAX];
	int len;
	int num1;//开始输入数组中个数
	int number;//输入数组中的数据
	int pos;//插入数组的位置
}seq_list,*seq_p;
seq_p create_seqlist();
int empty_seq(seq_p S);
int full_seq(seq_p S);
void output(seq_p S);
seq_p input(seq_p S);
seq_p inputall(seq_p S);

seq_p insert_head(seq_p S);
seq_p delete_head(seq_p S);
seq_p insert_tail(seq_p S);
seq_p delete_tail(seq_p S);
void seq_free(seq_p *S);

seq_p insert_pos(seq_p S);
seq_p delete_pos(seq_p S);
seq_p update(seq_p S);
int findpos(seq_p S);




#endif
                                   

makefile

EXE=seq
Objs=$(patsubst %.c,%.o,$(wildcard *.c))
CC=gcc
CFlags=-c -o
all:$(EXE)
$(EXE):$(Objs)
	$(CC) $^ -o $@
%.o:%c
	$(CC) $^ $(CFlags) $@
.PHONY:clean
clean:
	rm -f $(Objs) $(EXE)

02.单向链表

main.c

#include "link.h"
int main()
{
	node_p H = create_link();
	insert_head(H,12);
	insert_head(H,34);
	insert_head(H,70);
	insert_head(H,6);
	show_link(H);
	printf("第2个位置的元素为%d\n",search_pos(H,2));
	update_value(H,12,100);
	show_link(H);
	reverse_link(H);
	printf("逆置后\n");
	show_link(H);


	return 0;
}

link.c

#include "link.h"
//1、申请单链表(头结点)
node_p create_link()
{
	node_p H = (node_p)malloc(sizeof(node));
	if(H==NULL)
	{
		return NULL;
	}
	H->next = NULL;
	H->len  = 0;  //当只有头结点时,长度为0
	return H;
}
//2、申请数据结点
node_p create_node(int value)
{
	node_p new_node = (node_p)malloc(sizeof(node));
	if(new_node==NULL)
	{
		printf("申请空间失败\n");
		return NULL;
	}
	new_node->data = value;  //给数据结点的数据域赋值
	new_node->next = NULL;   //数据节点的指针域赋值
	return new_node;
}
//3、判空
int empty_link(node_p H)
{
	if(H==NULL){return -1;}
	return H->next==NULL?1:0;
}
//4、头插
void insert_head(node_p H,int value)
{
	if(H==NULL)
	{
		printf("入参为空,请检查\n");
		return;
	}
	//申请新结点
	node_p new = create_node(value);
	//让新结点指向原来头结点的后继结点
	new->next = H->next;
	//让头结点指向新结点
	H->next = new;
	//头结点保存的链表长度自增
	H->len++;
}
//5、尾插
void insert_tail(node_p H,int value)
{
	if(H==NULL)
	{
		printf("入参为空,请检查\n");
		return;
	}
	//1、找到尾结点
	node_p p = H;
	//尾结点的条件p->next==NULL;
	while(p->next!=NULL)
	{
		p = p->next;   //找下一个结点
	}
	//2、申请新的数据结点
	node_p new = create_node(value);
	//3、让最后一个结点的指针域指向新结点
	p->next = new;
	//4、因为新结点的指针域在申请后已经置NULL了,无需再次重置
	H->len++;
}
//6、输出单向链表
void show_link(node_p H)
{
	if(H==NULL){return;}
	if(empty_link(H))
	{
		printf("链表为空,无需数超出\n");
		return;
	}
	//从第一个结点开始输出,
	//到最后一个结点结束,最后一个结点需要进入循环
	node_p p = H->next;
	while(p!=NULL)
	{
		printf("%d->",p->data);
		p = p->next;
	}
	//退出循环说明p走到了NULL,遍历结束整条链表
	printf("NULL\n");
}
//7、头删
void delete_head(node_p H)
{
	if(H==NULL){return;}
	if(empty_link(H)){return;}
	//1、保存要删除结点的首地址
	node_p dele = H->next;
	//2、让头结点指向原来的第二个结点
	H->next = H->next->next;  //H->next = dele->next;
	free(dele);
	H->len--;
}
//8、尾删
void delete_tail(node_p H)
{
	if(H==NULL){return;}
	if(empty_link(H)){return;}
	//由于是单向链表只能向后查找
	//所以需要找到倒数第二个结点
	node_p p = H;
	while(p->next->next!=NULL)
	{
		p = p->next;
	}
	//退出循环说明找到倒数第二个结点
	node_p dele = p->next; //保存倒数第一个结点
	p->next = NULL;  //给倒数第二个结点的指针域置空
	free(dele);
	H->len--;
}
//9、按位置插入
void insert_pos(node_p H,int pos,int value)
{
	if(H==NULL){return;}
	//第一个循环变量i记录位置
	if(pos<=0)
	{
		printf("位置不合理\n");
		return;
	}
	int i = 0;
	//定义指针循环结点
	node_p p = H;
	for(i=0,p=H;i<pos-1;i++,p=p->next)
	{
		//判断位置不合理的情况
		if(p==NULL)
		{
			printf("插入位置不合理\n");
			return;
		}
	}
	node_p new = create_node(value);
	//新结点指向pos位置结点
	new->next = p->next;
	//pos-1位置结点,指向新结点
	p->next = new;
	H->len++;
}
//10、按位置删除
void dele_pos(node_p H,int pos)
{
	if(H==NULL){return;}
	if(pos<1)
	{
		printf("位置不合理\n");
		return;
	}
	int i;
	node_p p;
	//删除pos位置还是找到pos-1位置结点
	for(i=0,p=H;i<pos-1;i++,p=p->next);
	//找到pos-1位置结点后,判断是否有pos位置的结点
	if(p->next==NULL)
	{
		printf("位置不合理\n");
		return;
	}
	//保存要删除结点的首地址
	node_p dele = p->next;
	p->next = p->next->next; //p->next = dele->next;
	free(dele);
	H->len--;
}
//11、按位置查找返回元素的值
int search_pos(node_p H,int pos)
{
	if(H==NULL){return -2;}
	if(pos<1){return -1;}
	if(empty_link(H)){return -3;}
	int i;
	node_p p;
	for(i=1,p=H->next;i!=pos;i++,p=p->next)
	{
		if(p==NULL)
		{
			printf("位置不合理\n");
			return -1;
		}
	}
	return p->data;
}
//12、按值修改
void update_value(node_p H,int value,int new_value)
{
	if(H==NULL){return;}
	if(empty_link(H)){return;}
	node_p p = H->next;
	//循环整条链表
	for(;p!=NULL;p=p->next)
	{
		if(p->data==value)
		{
			p->data = new_value;
			return;
		}
	}
}
//13、逆置
void reverse_link(node_p H)
{
	if(H==NULL){return;}
	if(empty_link(H)){return;}
	if(H->next->next==NULL){return;}
	//提前将第二个结点开始链表保存下来
	node_p p = H->next->next;
	node_p q;
	//让原来的第一个结点变成现在的最后一个结点
	H->next->next = NULL;
	//循环头插
	//只要p的指向的结点不为空说明要头插
	while(p!=NULL)
	{
		//先保留下一个要头插结点的首地址
		q = p->next;
		//头插
		p->next = H->next;
		H->next = p;
		p = q;  //让p指向下一个要头插的结点
	}
}

link.h

#ifndef __LINK_H__
#define __LINK_H__
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
	union
	{
		int data; //数据节点的数据域
		int len;  //头结点的长度
	};
	struct node *next;
}node,*node_p;
//1、申请单链表(头结点)
node_p create_link();
//2、申请数据结点
node_p create_node(int value);
//3、判空
int empty_link(node_p H);
//4、头插
void insert_head(node_p H,int value);
//5、尾插
void insert_tail(node_p H,int value);
//6、输出单向链表
void show_link(node_p H);
//7、头删
void delete_head(node_p H);
//8、尾删
void delete_tail(node_p H);
//9、按位置插入
void insert_pos(node_p H,int pos,int value);
//10、按位置删除
void dele_pos(node_p H,int pos);
//11、按位置查找返回元素的值
int search_pos(node_p H,int pos);
//12、按值修改
void update_value(node_p H,int value,int new_value);
//13、逆置
void reverse_link(node_p H);


#endif

03.单向循环链表

main.c

#include "loop.h"
int main()
{
	node_p H = create_loop();
	insert_head(H,67);
	insert_head(H,90);
	insert_head(H,34);
	insert_head(H,8);
	show_loop(H);
	printf("H->next=%p\n",H->next);
	H = delete(H);  //删除头结点后链表已经没有头结点了
	//H需要重新被赋值
	show_no_head(H);
	return 0;
}

circle.c

#include "loop.h"
//1、申请单向循环链表
node_p create_loop()
{
	node_p H = (node_p)malloc(sizeof(node));
	if(H==NULL)
	{
		printf("申请空间失败\n");
		return NULL;
	}
	H->len=0;
	H->next = H;
	return H;
}
//2、申请结点
node_p create_node(int value)
{
	node_p new = (node_p)malloc(sizeof(node));
	new->next = NULL;
	new->data = value;
	return new;
}
//3、判空
int empty_loop(node_p H)
{
	if(H==NULL){return -1;}
	return H->next==H?1:0;
}
//4、头插
void insert_head(node_p H,int value)
{
	if(H==NULL){return;}
	node_p new = create_node(value);
	//新结点的后继指向头结点的后继
	new->next = H->next;
	H->next = new;
	H->len++;
}
//5、尾插
void insert_tail(node_p H,int value)
{
	if(H==NULL){return;}
	node_p p=H; //p用于遍历链表,找到最后一个结点
	while(p->next!=H)
	{
		p=p->next;
	}
	node_p new = create_node(value);
	//退出循环后p指向最后一个结点
	p->next = new;
	new->next=H;
	//new->next = p->next;
	//p->next = new;
	H->len++;
}
//6、头删
void dele_head(node_p H)
{
	if(H==NULL){return;}
	if(empty_loop(H)){return;}
	//保存要删除结点的首地址
	node_p p=H->next;
	//让头结点指向原来的第二个结点
	H->next=p->next;
	free(p);
	H->len--;
	return;
}
//7、尾删
void dele_tail(node_p H)
{
	if(H==NULL){return;}
	if(empty_loop(H)) {return;}
	node_p p=H;
	//尾删要找倒数第二个结点
	while(p->next->next!=H)
	{
		p=p->next;
	}
	//循环退出时p指向倒数第二个节点
	node_p q=p->next;
	p->next=H;
	free(q);
	//free(p->next);  //先释放最后一个结点
	//p->next = H;
	H->len--;
}
//8、输出
void show_loop(node_p H)
{
	if(H==NULL){return;}
	if(empty_loop(H)){return;}
	node_p p = H->next;
	while(p!=H)
	{
		printf("%d->",p->data);
		p = p->next;
	}
	printf("H\n");
}
//9、删除单向循环链表的头结点
//删除头结点后需要返回给主调函数处新的链表的头
node_p delete(node_p H)
{
	if(H==NULL){return NULL;}
	if(empty_loop(H)){return NULL;}
	//保存第一个结点的首地址
	node_p p = H->next;
	//找到最后一个结点
	node_p tail = H->next;
	while(tail->next!=H)
	{
		tail=tail->next;
	}
	//让最后一个结点的后继节点变成原来的第一个结点
	tail->next = p;
	//释放头结点
	free(H);
	return p;
}
//10、删除头结点后的单向循环链表的输出
void show_no_head(node_p H)
{
	if(H==NULL){return;}
	//不需要再判空
	//因为没有头结点了传过来的结点只要不是空说明链表中就有元素
	node_p p = H;
	do
	{
		printf("%d->",p->data);
		p = p->next;
	}while(p!=H);
	printf("H\n");
	//需要第一次循环时不判断条件
	//只能使用do··while
}

circle.h

#ifndef __LOOP_H__
#define __LOOP_H__
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
	union
	{
		int len;
		int data;
	};
	struct node *next;
}node,*node_p;
//1、申请单向循环链表
node_p create_loop();
//2、申请结点
node_p create_node(int value);
//3、判空
int empty_loop(node_p H);
//4、头插
void insert_head(node_p H,int value);
//5、尾插
void insert_tail(node_p H,int value);
//6、头删
void dele_head(node_p H);
//7、尾删
void dele_tail(node_p H);
//8、输出
void show_loop(node_p H);
node_p delete(node_p H);
//10、删除头结点后的单向循环链表的输出
void show_no_head(node_p H);




#endif

03.双向链表

main.c

#include "double.h"
int main()
{
	node_p H = create_double();
	insert_head(H,12);
	insert_head(H,34);
	insert_head(H,90);
	show(H);
	insert_pos(H,3,24);
	show(H);
	dele_pos(H,0);
	show(H);
	des_double(&H);
	printf("释放后\n");
	show(H);
	printf("H=%p\n",H);
	return 0;
}

double.c

#include "double.h"
//1、创建双向链表
node_p create_double()
{
	node_p H=(node_p)malloc(sizeof(node));
	if(H==NULL)
	{
		return NULL;
	}
	H->len=0;
	H->next=NULL;
	H->pri=NULL;
	return H;
}
//2、创建结点
node_p create_node(int data)
{
	node_p new = (node_p)malloc(sizeof(node));
	if(new==NULL){return NULL;}
	new->data = data;
	new->pri = NULL;
	new->next = NULL;
	return new;
}
//3、判空
int empty_double(node_p H)
{
	if(H==NULL){return -1;}
	return H->next==NULL;
}
//4、头插
void insert_head(node_p H,int value)
{
	if(H==NULL){return;}
	node_p new = create_node(value);
	//新结点的后继保存原来头结点的后继
	new->next = H->next;
	//新结点的前驱指向头结点
	new->pri = H;
	//头结点后继节点的前驱指向新结点
	if(H->next!=NULL)
	{
		H->next->pri = new;
	}
	//头结点的后继指向新结点
	H->next = new;
	H->len++;
}
//5、尾插
void insert_tail(node_p H,int value)
{
	if(H==NULL)
	{return;}
	node_p p = H;
	while(p->next!=NULL)
	{
		p = p->next;
	}
	node_p new = create_node(value);
	//新结点的前驱指向尾结点
	new->pri = p;
	//尾结点的后继指向新结点
	p->next = new;
	H->len++;
}
//6、输出
void show(node_p H)
{
	if(H==NULL){return;}
	if(empty_double(H)){return;}
	node_p p = H->next;
	while(p)
	{
		printf("%d->",p->data);
		p = p->next;
	}
	printf("NULL\n");
}
//7、任意位置插入
void insert_pos(node_p H,int pos,int value)
{
	if(H==NULL){return;}
	if(pos<=0){return;}
	//找到pos-1位置的结点
	int i;node_p p;
	for(i=0,p=H;i<pos-1;i++,p=p->next)
	{
		if(p==NULL)
		{
			printf("位置不合理\n");
			return;
		}
	}
	//退出循环时p指向pos-1位置的结点
	if(p==NULL)
	{
		printf("位置不合理\n");
		return;
	}
	node_p new = create_node(value);
	new->next = p->next;
	new->pri = p;
	if(p->next!=NULL)
	{
		p->next->pri = new;
	}
	p->next = new;
	H->len++;
}
//8、头删
void dele_head(node_p H)
{
	if(H==NULL){return;}
	if(empty_double(H)){return;}
	//保存要删除结点的首地址
	node_p del = H->next;
	//如果链表中节点个数多于一
	if(del->next!=NULL)
	{
		del->next->pri = H;
	}
	//让头结点的后继保存第一个结点的后继
	H->next = del->next;
	free(del);
	H->len--;
}
//9、尾删
void dele_tail(node_p H)
{
	if(H==NULL){return;}
	if(empty_double(H)){return;}
	//找到最后一个结点
	node_p p = H;
	while(p->next!=NULL)
	{
		p = p->next;
	}
	//退出循环时p是最后一个结点
	//让倒数第二个结点的后继指向NULL
	p->pri->next = NULL;
	free(p);
	H->len--;
}
//10、按位置删除
void dele_pos(node_p H,int pos)
{
	if(H==NULL){return;}
	if(empty_double(H)){return;}
	if(pos<=0){return;}
	//找到pos位置的结点
	int i;node_p p;
	for(i=0,p=H;i<pos;i++,p=p->next)
	{
		if(p==NULL)
		{
			printf("位置不合理\n");
			return;
		}
	}
	//循环结束p指向pos位置的结点
	if(p==NULL)
	{
		printf("位置不合理\n");
		return;
	}
	//pos+1结点的前驱指向pos-1结点 
	if(p->next!=NULL)
	{
		p->next->pri = p->pri;
	}
	//pos-1结点的后继指向pos+1结点 
	p->pri->next = p->next;
	free(p);
	H->len--;
}
//11、按值查找返回位置
int search_value(node_p H,int value)
{
	if(H==NULL)
	{return -1;}
	if(empty_double(H)){return -2;}
}
//12、按位置修改元素
void update_pos(node_p H,int pos,int new_value)
{
	if(H==NULL){return;}
	if(empty_double(H)){return;}
	if(pos<=0){return;}
}
//13、释放双向循环链表
void des_double(node_p *H)
{
	if(H==NULL||*H==NULL)
	{return;}
	while((*H)->next)
	{
		dele_head(*H);
	}
	//退出循环说明链表中只有头结点了
	free(*H);
	*H=NULL;
}

double.h

#ifndef __DOUBLE_H__
#define __DOUBLE_H__
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
    union
    {
        int len;
        int data;    
    };
    struct node *pri;     //指向前驱结点的指针
    struct node *next;    //指向后继结点的指针
}node,*node_p;
//1、创建双向链表
node_p create_double();
//2、创建结点
node_p create_node(int data);
//3、判空
int empty_double(node_p H);
//4、头插
void insert_head(node_p H,int value);
//5、尾插
void insert_tail(node_p H,int value);
//6、输出
void show(node_p H);
//7、任意位置插入
void insert_pos(node_p H,int pos,int value);
//8、头删
void dele_head(node_p H);
//9、尾删
void dele_tail(node_p H);
//10、按位置删除
void dele_pos(node_p H,int pos);
//13、释放双向循环链表
void des_double(node_p *H);



#endif

04.双向循环链表

main.c

#include "dloop.h"
int main()
{
	node_p H=(node_p)create_dloop();
	//1.头插
	printf("请输出头插的第一个数字双向链表:\n");
	insert_head(H,4);
	show(H);
	printf("请输出头插的第二个数字双向链表:\n");
	insert_head(H,3);
	show(H);
	printf("请输出头插的第三个数字双向链表:\n");
	insert_head(H,2);
	show(H);
	printf("请输出头插的第四个数字双向链表:\n");
	insert_head(H,1);
	show(H);
	//2.尾插
	printf("请输出尾插的第一个数字双向链表:\n");
	insert_tail(H,5);
	show(H);
	printf("请输出尾插的第二个数字双向链表:\n");
	insert_tail(H,6);
	show(H);
	//3.按位置插入
	printf("请输出按位置插入双向链表:\n");
	insert_pos(H,3,77);
	show(H);
	//4.头删
	printf("请输出头删双向链表:\n");
	dele_head(H);
	show(H);
	//5.尾删
	printf("请输出头删双向链表:\n");
	dele_tail(H);
	show(H);
	//6.按位置删除
	printf("请输出按位置删除双向链表:\n");
	delete_pos(H,3);
	show(H);
	//7.按位置查找返回值
	int ret=search_value(H,2);
	printf("请输出按位查找的返回值%d:\n",ret);
	show(H);
	printf("销毁前:\n");
	printf("%p\n",H);
	free_loop(&H);
	printf("销毁后:\n");
	printf("%p\n",H);

}

dloop.c

#include "dloop.h"
//1.创建双链表的空结点
node_p create_dloop()
{
	node_p H=(node_p)malloc(sizeof(node));
	if(H==NULL)
	{
		printf("申请内存失败.\n");
		return NULL;
	}
	H->pri=H;
	H->next=H;
	H->len=0;
	return H;
}
//2.申请结点
node_p create_node(int value)
{
	node_p new=(node_p)malloc(sizeof(node));
	new->next=NULL;
	new->data=value;
}
//3.判空
int empty_dloop(node_p H)
{
	if(H==NULL){
		printf("入参为空.\n");
		return -1;
	}
	return H->next==H?1:0;
}
//4.头插
void insert_head(node_p H,int value)
{
	if(H==NULL)
	{
		printf("入参为空.\n");
		return;
	}
	node_p new=create_node(value);
	new->next=H->next;
	new->pri=H;
	if(H->next!=NULL){
		H->next->pri=new;
	}
	H->next=new;
	H->len++;
}
//5.尾插
void insert_tail(node_p H,int value)
{
	if(H==NULL)
	{
		printf("入参为空.\n");
		return;
	}
	int i;
	node_p new=create_node(value);
	node_p p=H;
	//1.找到了最后一个结点的位置
	while(p->next!=H){
		p=p->next;
	}
	new->pri=p;
	new->next=H;
	p->next=new;
	H->pri=new;
	H->len++;
}
//6.按位置插入
void insert_pos(node_p H,int pos,int value)
{
	if(H==NULL){
		printf("入参为空.\n");
		return;
	}
	if(pos<0){
		printf("插入位置的数据不合理.\n");
		return;
	}
	int i;
	node_p p;
	for(i=1,p=H->next;i<pos-1;i++,p=p->next)
	{
		if(p==H){
			printf("位置不合理.\n");
			return;
		}
	}
	if(p==H){
		printf("位置不合理.\n");
		return;
	}
	node_p new=(node_p)create_node(value);
	new->next=p->next;
	new->pri=p;
	if(p->next!=H){
		p->next->pri=new;
	}
	p->next=new;
	H->len++;	
}
//7.输出
void show(node_p H)
{
	if(H==NULL){
		printf("入参为空.\n");
		return;
	}
	if(empty_dloop(H)){
		printf("双向循环链表为空,无输出.\n");
		return;
	}
	node_p p=H->next;
	while(p!=H){
		printf("%d->",p->data);
		p=p->next;
	}
	printf("NULL\n");
}
//8.头删
void dele_head(node_p H)
{
	if(H==NULL){
		printf("入参为空.\n");
		return;
	}
	if(empty_dloop(H)){
		printf("循环双链表为空,无数据可删除.\n");
		return;
	}
	node_p dele=H->next;
	//判断是否就一个数据
	if(dele->next!=H){
		dele->next->pri=H;
	}
	H->next=dele->next;
	free(dele);
	H->len--;
}
//9.尾删
void dele_tail(node_p H)
{
	if(H==NULL)
	{
		printf("入参为空.\n");
		return;
	}
	node_p p=H;
	while(p->next!=H){
		p=p->next;
	}
	p->pri->next=H;
	H->pri=p->pri;
	free(p);
	H->len--;
}
//10.按位置删除
void delete_pos(node_p H,int pos)
{
	if(H==NULL){
		printf("入参为空.\n");
		return;
	}
	if(empty_dloop(H)){
		printf("双向链表为空.\n");
		return;
	}
	node_p p;
	int i;
	for(i=1,p=H->next;i<pos;i++,p=p->next){
		if(p==H){
			printf("位置不合理.\n");
			return;
		}
	}
	if(p==H){
		printf("位置不合理.\n");
		return;
	}
	//1.pos+1结点的前驱指向pos-1结点
	if(p->next!=H){
		p->next->pri=p->pri;
	}
	//2.pos-1结点的后继指向pos+1结点
	p->pri->next=p->next;
	free(p);
	H->len--;
}

//11.按位置查找返回值
int search_value(node_p H,int pos)
{
	if(H==NULL)
	{
		printf("入参为空.\n");
		return -1;
	}
	if(empty_dloop(H)){
		printf("双向循环链表为空.\n");
		return -2;
	}
	int i;
	node_p p;
	for(i=1,p=H->next;i<pos;i++,p=p->next){
		if(p==H){
			printf("位置不合理.\n");
			return -3;
		}
	}
	if(p==H){
		printf("位置不合理.\n");
		return -3;
	}
	return p->data;
}
//12.释放链表
void free_loop(node_p *H)
{
	if(H==NULL||*H==NULL)
	{
		printf("入参为空.\n");
		return;
	}
	while((*H)->next!=(*H)){
		dele_head(*H);
	}
	free(*H);
	*H==NULL;
}

dloop.h

#ifndef __DLOOP_H__
#define __DLOOP_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node
{
	union{
	  int len;
	  int data;
	};
	struct node *pri;
	struct node *next;
}node,*node_p;

node_p create_dloop();
node_p create_node(int value);
int empty_dloop(node_p H);
void insert_head(node_p H,int value);
void insert_tail(node_p H,int value);
void insert_pos(node_p H,int pos,int value);
void show(node_p H);
void dele_head(node_p H);
void dele_tail(node_p H);
void delete_pos(node_p H,int pos);
int search_value(node_p H,int pos);
void free_loop(node_p *H);



#endif


网站公告

今日签到

点亮在社区的每一天
去签到