0719|数据结构day5(双向链表+双向循环链表)

目录

一、思维导图

二、作业

2.1 单向链表简单选择排序

2.2 单向链表按元素插入

2.3 单向链表按元素修改

三、双链表

 3.1 双向链表结构体建立

3.2 双向链表节点创建

3.3 双向链表头插

3.4 双向链表尾插

3.5 双向链表头删

3.6 双向链表尾删

3.7 双向链表遍历

3.8 双链表全部代码

四、双向循环链表

 4.1 双向循环链表结构体建立

4.2 双向循环链表节点创建

4.3 双向循环链表头插

4.4 双向循环链表尾插

4.5 双向循环链表头删

4.6 双向循环链表尾删

4.7 双向循环链表遍历

4.8 双向循环链表所有代码


一、思维导图

二、作业

2.1 单向链表简单选择排序

/*
 * function:    简单选择排序
 * @param [ in] 
 * @param [out] 
 * @return      
 */
void paixu(Linklist L)
{
	//判断链表是否为空
	//判断链表只有有一个节点
	if( NULL==L || L->next==NULL )
	{
		return;
	}
	int i,j;
	int len=Len_linklist(L);
	Linklist p=L;
	Linklist k=NULL;
	for(i=0;i<len-1;i++)
	{
		Linklist q=p;
		k=q;
		for(j=i+1,p=L;j<len;j++,p=p->next)
		{
			if(q->data < p->data)
			{
				k=p;
			}
		}
		if(k != q)
		{
			datatype t=k->data;k->data=q->data;q->data=t;
		}
	}
}

2.2 单向链表按元素插入

/*
 * function:    按元素插入
 * @param [ in] 
 * @param [out] 
 * @return      
 */
Linklist insert_by_data(datatype key,datatype e,Linklist L)
{
	int insert_pos=search_by_data(key,L);
	if(insert_pos==-1)
		return L;
	L=insert_by_pos(insert_pos,e,L);
	return L;
}

2.3 单向链表按元素修改

/*
 * function:    按元素修改
 * @param [ in] 
 * @param [out] 
 * @return      
 */
Linklist modify_by_data(datatype key,datatype e,Linklist L)
{
	int modify_pos=search_by_data(key,L);
	if(modify_pos==-1)
		return L;
	L=modify_by_pos(modify_pos,e,L);
	return L;
}

三、双链表

        单向链表只可以向后遍历,使用起来不方便,那么引出双向链表,可以向前遍历。

 3.1 双向链表结构体建立

typedef char datatype[20];
typedef struct Node
{
	//数据域
	datatype data;
	//指针域:下一节点地址
	struct Node *next;
	//指针域:上一节点地址
	struct Node *prev;
}*DouleLink;

3.2 双向链表节点创建

/*
 * function:    申请节点
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink  create_node()
{
	DouleLink node=(DouleLink)malloc(sizeof(struct Node));
	if(NULL==node)
	{
		return NULL;
	}
	strcpy(node->data,"");
	node->next=node->prev=NULL;
	return node;
}

3.3 双向链表头插

/*
 * function:    头插
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink insert_head(datatype e,DouleLink L)
{
	//1.创建新节点
	DouleLink s=create_node();
	if(NULL==s)
		return L;
	//
	strcpy(s->data,e);
	if(NULL!=L)
	{
		s->next=L;
		L->prev=s;
	}
	L=s;
	return L;
}

3.4 双向链表尾插

/*
 * function:    尾插
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink insert_rear(datatype e,DouleLink L)
{
	//1.创建新节点
	DouleLink s=create_node();
	if(NULL==s)
		return L;
	strcpy(s->data,e);
	//2.链表为空
	if(NULL==L)
	{	
		L=s;
		return L;
	}
	//3.已有多个节点
	//找到尾部节点
	DouleLink rear=L;
	while(rear->next!=NULL)
	{
		rear=rear->next;
	}
	rear->next=s;
	s->prev=rear;
	return L;
}

3.5 双向链表头删

/*
 * function:    头删
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink delete_head(DouleLink L)
{
	//1.如果链表为空
	if(NULL==L)
		return L;
	//2.判断链表只有一个节点
	if(NULL==L->next)
	{
		free(L);
		L=NULL;
		return L;
	}
	//3.有多个节点
	DouleLink q=L->next;
	strcpy(L->data,q->data);
	L->next=q->next;
	if(q->next!=NULL)
		q->next->prev=L;
	free(q);
	q=NULL;
	return L;
}

3.6 双向链表尾删

/*
 * function:    头删
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink delete_head(DouleLink L)
{
	//1.如果链表为空
	if(NULL==L)
		return L;
	//2.判断链表只有一个节点
	if(NULL==L->next)
	{
		free(L);
		L=NULL;
		return L;
	}
	//3.有多个节点
	DouleLink q=L->next;
	strcpy(L->data,q->data);
	L->next=q->next;
	if(q->next!=NULL)
		q->next->prev=L;
	free(q);
	q=NULL;
	return L;
}

3.7 双向链表遍历

/*
 * function:    循环输出
 * @param [ in] 
 * @param [out] 
 * @return      
 */
void output(DouleLink L)
{
	//1.如果为空
	if(NULL==L)
	{
		return;
	}
	//2.如果存在节点
	//正向遍历
	puts("正向遍历:");
	while(L->next!=NULL)
	{
		printf("%s\t",L->data);
		L=L->next;
	}
	printf("%s\n",L->data);
	//逆向遍历
	puts("逆向遍历:");
	while(L!=NULL)
	{
		printf("%s\t",L->data);
		L=L->prev;
	}
	puts("");
}

3.8 双链表全部代码

double_head.h

#ifndef __HEAD__H__
#define __HEAD__H__

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef char datatype[20];
typedef struct Node
{
	//数据域
	datatype data;
	//指针域:下一节点地址
	struct Node *next;
	//指针域:上一节点地址
	struct Node *prev;
}*DouleLink;

DouleLink insert_head(datatype e,DouleLink L);
void output(DouleLink L);
DouleLink insert_rear(datatype e,DouleLink L);
DouleLink delete_head(DouleLink L);
DouleLink delete_head(DouleLink L);
DouleLink delete_rear(DouleLink L);
#endif

double_main.c

#include "double_head.h"
int main(int argc, const char *argv[])
{
	DouleLink L=NULL;
	int n;
	datatype e;
	printf("please enter n:");
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		printf("please enter e:");
		scanf("%s",e);
	//	L=insert_head(e,L);
		L=insert_rear(e,L);
	}
	//循环输出
	output(L);
	//头删
	L=delete_head(L);	
	printf("头删后:\n");
	output(L);
	puts("");
	//尾删
	L=delete_rear(L);	
	printf("尾删后:\n");
	output(L);
	puts("");
	return 0;
}

double_test.c

#include "double_head.h"
/*
 * function:    申请节点
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink  create_node()
{
	DouleLink node=(DouleLink)malloc(sizeof(struct Node));
	if(NULL==node)
	{
		return NULL;
	}
	strcpy(node->data,"");
	node->next=node->prev=NULL;
	return node;
}


/*
 * function:    头插
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink insert_head(datatype e,DouleLink L)
{
	//1.创建新节点
	DouleLink s=create_node();
	if(NULL==s)
		return L;
	//
	strcpy(s->data,e);
	if(NULL!=L)
	{
		s->next=L;
		L->prev=s;
	}
	L=s;
	return L;
}

/*
 * function:    循环输出
 * @param [ in] 
 * @param [out] 
 * @return      
 */
void output(DouleLink L)
{
	//1.如果为空
	if(NULL==L)
	{
		return;
	}
	//2.如果存在节点
	//正向遍历
	puts("正向遍历:");
	while(L->next!=NULL)
	{
		printf("%s\t",L->data);
		L=L->next;
	}
	printf("%s\n",L->data);
	//逆向遍历
	puts("逆向遍历:");
	while(L!=NULL)
	{
		printf("%s\t",L->data);
		L=L->prev;
	}
	puts("");
}

/*
 * function:    尾插
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink insert_rear(datatype e,DouleLink L)
{
	//1.创建新节点
	DouleLink s=create_node();
	if(NULL==s)
		return L;
	strcpy(s->data,e);
	//2.链表为空
	if(NULL==L)
	{	
		L=s;
		return L;
	}
	//3.已有多个节点
	//找到尾部节点
	DouleLink rear=L;
	while(rear->next!=NULL)
	{
		rear=rear->next;
	}
	rear->next=s;
	s->prev=rear;
	return L;
}

/*
 * function:    头删
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink delete_head(DouleLink L)
{
	//1.如果链表为空
	if(NULL==L)
		return L;
	//2.判断链表只有一个节点
	if(NULL==L->next)
	{
		free(L);
		L=NULL;
		return L;
	}
	//3.有多个节点
	DouleLink q=L->next;
	strcpy(L->data,q->data);
	L->next=q->next;
	if(q->next!=NULL)
		q->next->prev=L;
	free(q);
	q=NULL;
	return L;
}

/*
 * function:    尾删
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink delete_rear(DouleLink L)
{
	//1.如果链表为空
	if(NULL==L)
		return L;
	//2.判断链表只有一个节点
	if(NULL==L->next)
	{
		free(L);
		L=NULL;
		return L;
	}
	//3.有多个节点
	DouleLink rear=L;
	while(rear->next!=NULL)
		rear=rear->next;

	rear->prev->next=NULL;
	free(rear);
	rear=NULL;
	return L;
}

四、双向循环链表

        因为双向链表在找尾节点是,需要从第一个节点遍历到最后一个节点,时间复杂度高,而且单链表只能向后遍历,不可以向前,所以引出双向循环链表。双向循环链表最大特点是:不需要通过循环找到尾节点,相对方便

 4.1 双向循环链表结构体建立

typedef char datatype[20];
typedef struct Node
{
	//数据域
	datatype data;
	//指针域
	struct Node *next;
	//指针域
	struct Node *prev;
}*DouleLink;

4.2 双向循环链表节点创建

/*
 * function:    申请节点
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink  create_node()
{
	DouleLink node=(DouleLink)malloc(sizeof(struct Node));
	if(NULL==node)
	{
		return NULL;
	}
	strcpy(node->data,"");
	node->next=node->prev=NULL;
	return node;
}

4.3 双向循环链表头插

/*
 * function:    头插
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink insert_head(datatype e,DouleLink L)
{
	//1.创建新节点
	DouleLink s=create_node();
	if(NULL==s)
		return L;
	//
	strcpy(s->data,e);
	if(NULL!=L)
	{
		s->next=L;
		L->prev=s;
	}
	L=s;
	return L;
}

4.4 双向循环链表尾插

/*
 * function:    尾插
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink insert_rear(datatype e,DouleLink L)
{
	//1.创建新节点
	DouleLink s=create_node();
	if(NULL==s)
		return L;
	strcpy(s->data,e);
	//2.链表为空
	if(NULL==L)
	{	
		L=s;
		return L;
	}
	//3.已有多个节点
	//找到尾部节点
	DouleLink rear=L;
	while(rear->next!=NULL)
	{
		rear=rear->next;
	}
	rear->next=s;
	s->prev=rear;
	return L;
}

4.5 双向循环链表头删

/*
 * function:    头删
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink delete_head(DouleLink L)
{
	//1.如果链表为空
	if(NULL==L)
		return L;
	//2.判断链表只有一个节点
	if(NULL==L->next)
	{
		free(L);
		L=NULL;
		return L;
	}
	//3.有多个节点
	DouleLink q=L->next;
	strcpy(L->data,q->data);
	L->next=q->next;
	if(q->next!=NULL)
		q->next->prev=L;
	free(q);
	q=NULL;
	return L;
}

4.6 双向循环链表尾删

/*
 * function:    尾删
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink delete_rear(DouleLink L)
{
	//1.如果链表为空
	if(NULL==L)
		return L;
	//2.判断链表只有一个节点
	if(NULL==L->next)
	{
		free(L);
		L=NULL;
		return L;
	}
	//3.有多个节点
	DouleLink rear=L;
	while(rear->next!=NULL)
		rear=rear->next;

	rear->prev->next=NULL;
	free(rear);
	rear=NULL;
	return L;
}

4.7 双向循环链表遍历

/*
 * function:    循环输出
 * @param [ in] 
 * @param [out] 
 * @return      
 */
void output(DouleLink L)
{
	//1.如果为空
	if(NULL==L)
	{
		return;
	}
	//2.如果存在节点
	//正向遍历
	puts("正向遍历:");
	while(L->next!=NULL)
	{
		printf("%s\t",L->data);
		L=L->next;
	}
	printf("%s\n",L->data);
	//逆向遍历
	puts("逆向遍历:");
	while(L!=NULL)
	{
		printf("%s\t",L->data);
		L=L->prev;
	}
	puts("");
}

4.8 双向循环链表所有代码

head.h

#ifndef __HEAD__H__
#define __HEAD__H__

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef char datatype[20];

typedef struct Node
{
	//数据域
	datatype data;
	//指针域
	struct Node *next;
	//指针域
	struct Node *prev;
}*DouleLink;

DouleLink insert_head(datatype e,DouleLink L);
void output(DouleLink L);
DouleLink insert_rear(datatype e,DouleLink L);
DouleLink delete_head(DouleLink L);
DouleLink delete_head(DouleLink L);
DouleLink delete_rear(DouleLink L);
#endif

main.c

#include "double_head.h"
int main(int argc, const char *argv[])
{
	DouleLink L=NULL;
	int n;
	datatype e;
	printf("please enter n:");
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		printf("please enter e:");
		scanf("%s",e);
	//	L=insert_head(e,L);
		L=insert_rear(e,L);
	}
	//循环输出
	output(L);
	//头删
	L=delete_head(L);	
	printf("头删后:\n");
	output(L);
	puts("");
	//尾删
	L=delete_rear(L);	
	printf("尾删后:\n");
	output(L);
	puts("");
	return 0;
}

test.c

#include "double_head.h"
/*
 * function:    申请节点
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink  create_node()
{
	DouleLink node=(DouleLink)malloc(sizeof(struct Node));
	if(NULL==node)
	{
		return NULL;
	}
	strcpy(node->data,"");
	node->next=node->prev=NULL;
	return node;
}


/*
 * function:    头插
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink insert_head(datatype e,DouleLink L)
{
	//1.创建新节点
	DouleLink s=create_node();
	if(NULL==s)
		return L;
	//
	strcpy(s->data,e);
	if(NULL!=L)
	{
		s->next=L;
		L->prev=s;
	}
	L=s;
	return L;
}

/*
 * function:    循环输出
 * @param [ in] 
 * @param [out] 
 * @return      
 */
void output(DouleLink L)
{
	//1.如果为空
	if(NULL==L)
	{
		return;
	}
	//2.如果存在节点
	//正向遍历
	puts("正向遍历:");
	while(L->next!=NULL)
	{
		printf("%s\t",L->data);
		L=L->next;
	}
	printf("%s\n",L->data);
	//逆向遍历
	puts("逆向遍历:");
	while(L!=NULL)
	{
		printf("%s\t",L->data);
		L=L->prev;
	}
	puts("");
}

/*
 * function:    尾插
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink insert_rear(datatype e,DouleLink L)
{
	//1.创建新节点
	DouleLink s=create_node();
	if(NULL==s)
		return L;
	strcpy(s->data,e);
	//2.链表为空
	if(NULL==L)
	{	
		L=s;
		return L;
	}
	//3.已有多个节点
	//找到尾部节点
	DouleLink rear=L;
	while(rear->next!=NULL)
	{
		rear=rear->next;
	}
	rear->next=s;
	s->prev=rear;
	return L;
}

/*
 * function:    头删
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink delete_head(DouleLink L)
{
	//1.如果链表为空
	if(NULL==L)
		return L;
	//2.判断链表只有一个节点
	if(NULL==L->next)
	{
		free(L);
		L=NULL;
		return L;
	}
	//3.有多个节点
	DouleLink q=L->next;
	strcpy(L->data,q->data);
	L->next=q->next;
	if(q->next!=NULL)
		q->next->prev=L;
	free(q);
	q=NULL;
	return L;
}

/*
 * function:    尾删
 * @param [ in] 
 * @param [out] 
 * @return      
 */
DouleLink delete_rear(DouleLink L)
{
	//1.如果链表为空
	if(NULL==L)
		return L;
	//2.判断链表只有一个节点
	if(NULL==L->next)
	{
		free(L);
		L=NULL;
		return L;
	}
	//3.有多个节点
	DouleLink rear=L;
	while(rear->next!=NULL)
		rear=rear->next;

	rear->prev->next=NULL;
	free(rear);
	rear=NULL;
	return L;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值