数据结构实验 3 双向链表的实现

写在前面:双向链表和单链表非常相似,会单链表的人完全可以不用看这篇文章。看过鄙人的单链表的话可以只看下面提及的几行代码,其余代码是完全一致的。

1.双向链表与单链表在结构定义上非常相似,只是双向链表比单链表多一个指针域指向该结点的直接前驱。(参考Two-way_Linked_List.h中的结构体定义第8行)

2.双向链表与单链表在大部分的基本操作上也非常相似,只是双向链表在头插法、尾插法、插入结点、删除结点操作上需要对前指针域进行更改。(参考Two-way_Linked_List.c中的Create_Head函数第21、22行、Create_Behind函数第41行、Insert_List函数146行、Delete_List函数165行)

3.因此,双向链表的测试函数可以直接沿用单链表的测试函数。

一、实验目的

1.掌握双向链表的定义。

2.掌握双向链表和单链表的区别和联系。

3.掌握双向链表的初始化、头插法、尾插法、打印、判断空表、清空链表、求表长、按址查找、按值查找、插入、删除等基本操作。

4. 了解双向链表和单链表的优缺点,能在不同情况下选择合适的存储方式。

二、实验要求

1. 写出双向链表的操作的详细算法步骤;

2. 使用C/C++实现双向链表,并编译运行。

三、实验过程

实验环境:visual studio 2017

实验步骤:

1.初始化链表L,定义函数名为Init_List;

2.头插法创建链表L,定义函数名为Create_Head;

3.尾插法创建链表L,定义函数名为Create_Behind;

4.打印链表L,定义函数名为Print_List;

5.判断链表L是否为空表,定义函数名为Empty_List;

6.清空链表L,定义函数名为Clear_List;

7.求链表L表长,定义函数名为Length_List;

8.查找第location个结点的元素值,定义函数名为Get_Data;

9.查找第一个值为e的元素的位置,定义函数名为Locate_Data;

10.在顺序表L第location个位置插入一个元素e,定义函数名为Insert_List;

11.将顺序表L第location个元素删除,定义函数名为Delete_List;

Two-way_Linked_List.h

#include<stdio.h>       //调用头文件
#include<stdlib.h>      //调用头文件
#define ELEMTYPE int    //用#define定义一个标识符ELEMTYPE表示int

typedef struct Lnode      //构建一个结构体存储链表信息
{
	ELEMTYPE data;         //数据域——存储元素值
    struct Lnode* prior;    //前指针域——指向该结点的直接前驱
	struct Lnode* next;    //指针域——指向该结点的直接后继
}LNode,*List;    //LNode为结构体类型别名,List为结构体指针

void Init_List(List* L);      //声明初始化函数-Init_List
void Create_Head(List* L);    //声明头插法创建链表函数-Create_Head
void Create_Behind(List* L);  //声明尾插法创建链表函数-Create_Behind
void Print_List(List L);      //声明打印函数-Print_List
bool Empty_List(List L);      //声明判断空表函数-Empty_List
void Clear_List(List* L);     //声明清空函数-Clear_List
int Length_List(List L);      //声明求表长函数-Length_List
void Get_Data(List L, int location, ELEMTYPE* e);    
//声明按位置查找元素值函数-Get_Data
int Locate_Data(List L, ELEMTYPE e);    
//声明按值查找元素位置函数-Locate_Data
void Insert_List(List* L, int i, ELEMTYPE e); //声明插入函数-Insert_List
void Delete_List(List* L, int i);    //声明删除函数-Delete_List

Two-way_Linked_List.c

#include "Linked_List.h"    //调用头文件

void Init_List(List* L)    //初始化链表L
{
	(*L) = (List)malloc(sizeof(LNode));  //用malloc给链表L分配一块内存
	(*L)->prior = (*L)->next = NULL;     //将头指针置为空
}

void Create_Head(List* L)    //头插法创建链表L
{
	int length;              //定义整型变量length表示链表L表长
	printf("Please input the length:");    //提示输入表长length
	scanf("%d", &length);                  //输入表长length
	for (int n = 1; n <= length; n++)      //向链表L中添加n个结点
	{
		List p;                             //定义结构体指针类型变量p
		p = (List)malloc(sizeof(LNode));    //用malloc给p分配一块内存
		printf("Please input the data:");   //提示输入结点p的数据域
		scanf("%d", &p->data);              //输入结点p的数据域
		p->next = (*L)->next;      //p作为新的首元结点,后指针域指向原来的首元结点
        (*L)->next->prior = p;    //原来的首元结点的前指针域指向新首元结点-p
        p->prior = (*L);      //前指针域指向头结点
		(*L)->next = p;      //更新首元结点
	}
}

void Create_Behind(List* L)    //尾插法创建链表L
{
	int length;          //定义整型变量length表示链表L长度
	List rear = (*L);    //rear指向尾结点,初始时指向头结点
	printf("Please input the length:");    //提示输入表长length
	scanf("%d", &length);                  //输入表长length
	for (int n = 1; n <= length; n++)      //向链表L中添加n个结点
	{
		List p;                              //定义结构体指针类型变量p
		p = (List)malloc(sizeof(LNode));      //用malloc给p分配一块内存
		printf("Please input the data:");    //提示输入结点p的数据域
		scanf("%d", &p->data);               //输入结点p的数据域
		p->next = NULL;                      //p为尾结点,后指针域为空
        p->prior = rear;    //p的前指针域指向原来的尾结点
		rear->next = p;    //原来的尾结点rear的后指针域指向现在的尾结点p
		rear = p;          //更新尾结点
	}
}

void Print_List(List L)    //打印链表L
{
	List p = L;            //定义结构体指针类型变量p为头结点
	printf("The linked list is:");    //提示输出链表L
	while (p->next != NULL)           //扫描链表L
	{
		p = p->next;                  //当前p为原来p的后继结点
		printf("%d ", p->data);       //打印p的数据域
	}
	printf("\n");                    //换行
}

bool Empty_List(List L)     		 //判断链表是否为空
{
	if (L->next == NULL)    			 //链表为空
	{
		printf("This list is empty.\n");    //表示链表L为空
		return true;   						 //返回true
	}
	else                     				 //链表L不为空
	{
		printf("This list isn't empty.\n"); //表示链表L不为空
		return false;    						 //返回false
	}
}

void Clear_List(List* L)      //清空链表L
{
	List p = (*L)->next,q;    //定义结构体指针变量q,p为首元结点
	while (p != NULL)         //扫描链表
	{
		q = p->next;          //q为p的后继结点
		free(p);	           //释放结点p所占空间
		p = NULL;            //防止出现悬空指针(失效指针)
		p = q;               //当前p为原来p的后继结点
	}
	(*L)->next = NULL;      //清空链表L后头指针为空
}

int Length_List(List L)    //求链表L表长(元素个数)
{
	int length = 0;        //定义整型变量length记录链表表长
	L = L->next;           //L为首元结点
	while (L != NULL)      //扫描链表L
	{
		length++;          //表长length加1
		L = L->next;       //当前L为原来L的后继结点
	}
	return length;        //返回链表L表长
}

void Get_Data(List L, int location,ELEMTYPE* e)    
//从首元结点开始查找第location个结点并将该结点的数据域赋值给e(按位置查找元素值)
{
	int length = (Length_List(L));   //定义整型变量length表示链表L表长
	if (location<1 || location>length)    //判断location的值是否合法
	{
		printf("get failed\n");           //提示location的值不合法
		return;                           //结束函数
	}
	else                                 //合法
	{
		List p = L;                      //定义结构体指针类型变量p
		for (int j = 0; j < location; j++)   //扫描链表顺序存取
		{
			p = p->next;                     //当前p为原来p的后继结点
		}
		(*e) = p->data;           //将第location个结点的数据域赋值给e
	}
}

int Locate_Data(List L, ELEMTYPE e)    //查找元素e在链表L中的位置(按值查找元素位置)
{
	List p=L;    //定义结构体指针类型变量p
	for (int location = 1; location <= Length_List(L); location++)    //扫描链表L
	{
		p = p->next;            //当前p指向原来p的后继结点
		if (p->data == e)       //判断p指向的结点的数据域与e是否相等
			return location;    //相等则返回元素e的位置location
	}
	printf("locate failed\n");         //提示查找失败
	return 0;                          //查找失败返回0
}

void Insert_List(List* L, int location, ELEMTYPE e)    //在第location个结点上插入元素e
{
	if (location > Length_List(*L) + 1 || location < 1)    //判断location的值是否合法
	{
		printf("insert failed\n");    //location的值非法
		return;                       //退出函数
	}
	List p = (*L);                    //定义结构体指针类型变量p
	for (int n = 1; n < location; n++)//查找链表的第location-1个结点
	{
		p = p->next;                  //当前p为原来p的后继结点
	}
	List q;                          //定义结构体指针类型变量q
	q = (List)malloc(sizeof(LNode)); //用malloc给q分配一块内存
	q->data = e;                     //元素e存放至结点q的数据域
    q->prior = p;      //结点q的前指针域指向第location-1个结点p
	q->next = p->next;               //p的后继结点存放至q的后指针域
	p->next = q;                     //q为p的后继结点
}

void Delete_List(List* L, int location)    //删除第location个结点
{
	if (location<1 || location>Length_List(*L))    //判断location的值是否合法
	{
		printf("delete failed\n");      //location的值非法
		return;                         //退出函数
	}
	List p = (*L);                     //定义结构体指针类型变量p
	for (int n = 1; n < location ; n++)    //查找链表的第location-1个结点
	{
		p = p->next;      //当前p为原来p的后继结点
	}
	List q = p->next;     //定义结构体指针类型变量q为第location个结点
	p->next = q->next;     //第location-1个结点的后指针域改为第location个结点的后继结点
    q->next->prior = q->prior;		//第location+1个结点的前指针域指向第location-1个结点
	free(q);     //释放第location个元素的空间
	q = NULL;    //防止出现悬空指针(无效指针)
}

以下为测试函数

1.测试初始化函数Init_List;头插法函数Create_Head;打印函数Print_List.

#include "Linked_List.h"    //调用头文件

int main(void)        //main()函数
{
	List L;           //定义结构体指针变量L
	Init_List(&L);    //调用Init_List函数将链表L初始化
	Create_Head(&L);  //调用Create_Head函数用头插法创建链表L
	Print_List(L);    //调用Print_List函数打印链表L
	return 0;         //返回值
}

2.测试尾插法函数Create_Behind.

#include "Linked_List.h"    //调用头文件

int main(void)            //main()函数
{
	List L;		        //定义结构体指针变量L
	Init_List(&L);        //调用Init_List函数将链表L初始化
	Create_Behind(&L);    //调用Create_Behind函数用尾插法创建链表L
	Print_List(L);        //调用Print_List函数打印链表L
	return 0;             //返回值
}

3.测试判断空表函数Empty_List.

#include "Linked_List.h"    //调用头文件

int main(void)		    //main()函数
{
	List L;		       //定义结构体指针变量L
	Init_List(&L);       //调用Init_List函数将链表L初始化
	Empty_List(L);		//调用Empty_List函数判断链表L是否为空
	Create_Behind(&L);	//调用Create_Behind函数用尾插法创建链表L
	Empty_List(L);		//调用Empty_List函数判断链表L是否为空
	return 0;				//返回值
}

4.测试清空链表函数Clear_List.

#include "Linked_List.h"    //调用头文件

int main(void)		       //main()函数
{
	List L;		       //定义结构体指针变量L
	Init_List(&L);		//调用Init_List函数将链表L初始化
	Create_Behind(&L);	//调用Create_Behind函数用尾插法创建链表L
	Empty_List(L);		//调用Empty_List函数判断链表L是否为空
	Clear_List(&L);		//调用Clear_List函数清空链表L
	Empty_List(L);		//调用Empty_List函数判断链表L是否为空
	return 0;            //返回值
}

5.测试求表长函数Length_List.

#include "Linked_List.h"    //调用头文件

int main(void)		       //main()函数
{
	List L;		          //定义结构体指针变量L
	Init_List(&L);		   //调用Init_List函数将链表L初始化
	Create_Head(&L);		   //调用Create_Head函数用头插法创建链表L
    printf("The length of this list is:%d\n", Length_List(L));     
    //输出表长
	return 0;					//返回值
}

6.测试按址查找函数Get_Data.

#include "Linked_List.h"    //调用头文件

int main(void)		        //main()函数
{
	List L;		          	//定义结构体指针变量L
	Init_List(&L);		   	//调用Init_List函数将链表L初始化
	Create_Head(&L);	   	   	//调用Create_Head函数用头插法创建链表L
	Print_List(L);          	//调用Print_List函数打印链表L
	ELEMTYPE e;			   	//定义查找到的元素e
	int location;		  	  	//定义待查找位置location
	printf("Please input the location of the element you want to get:");    //提示输入待查找位置location
	scanf("%d", &location);		       //输入待查找位置location
	Get_Data(L,location,&e);		       //调用Get_Data函数按址查找
	printf("The element is:%d", e);    //输出查找到的元素e
	return 0;								//返回值
}

7.测试按值查找函数Locate_List

#include "Linked_List.h"    //调用头文件

int main(void)		   //main()函数
{
	List L;		       //定义结构体指针变量L
	Init_List(&L);		//调用Init_List函数将链表L初始化
	Create_Behind(&L);	//调用Create_Behind函数用头插法创建链表L
	Print_List(L);       //调用Print_List函数打印链表L
	ELEMTYPE e;			//定义待查找结点的数据域e
	printf("Please input the element you want to search:");		
    //提示输入待查找结点的数据域e
	scanf("%d", &e);		//输入带查找元素e
	printf("The location of this element is:%d", Locate_Data(L, e));	
    //调用Locate_Data函数按值查找结点位置并输出
	return 0;				//返回值
}

8.测试插入函数Insert_List

#include "Linked_List.h"    //调用头文件

int main(void)		       //main()函数
{
	List L;		           //定义结构体指针变量L
	Init_List(&L);		    //调用Init_List函数将链表L初始化
	Create_Behind(&L);		//调用Create_Behind函数用头插法创建链表L
	Print_List(L);           //调用Print_List函数打印链表L
	ELEMTYPE e;				//定义待查找结点的数据域e
	printf("Please input the element you want to search:");		//提示输入待查找结点的数据域e
	scanf("%d", &e);		//输入带查找元素e
	printf("The location of this element is:%d", Locate_Data(L, e));	
    //调用Locate_Data函数按值查找结点位置并输出
	return 0;				//返回值
}

9.测试删除函数Delete_List

#include "Linked_List.h"    //调用头文件

int main(void)		       //main()函数
{
	List L;		          //定义结构体指针变量L
	Init_List(&L);		   //调用Init_List函数将链表L初始化
	Create_Behind(&L);	   //调用Create_Behind函数用头插法创建链表L
	Print_List(L);		   //调用Print_List函数打印链表L
	int location;        //定义待删除结点位置location
	printf("The location of the element to be deleted is:");   
 	//提示输入删除结点的位置
	scanf("%d", &location);        //输入需要删除结点的位置
	Delete_List(&L, location);
    //调用Delete_List函数删除第location个结点
	Print_List(L);		         //调用Print_List函数打印链表L
	printf("The length of this list is:%d\n", Length_List(L));    
    //输出表长
	return 0;		  //返回值
}

四、实验结果及分析

测试函数

测试用例

运行结果

Init_List Creat_Head

Print_List

5

1,2,3,4,5

Please input the length:5

Please input the data:1

Please input the data:2

Please input the data:3

Please input the data:4

Please input the data:5

The linked list is:5 4 3 2 1

-1

Please input the length:-1

The linked list is:

Create_Behind

5

1,2,3,4,5

Please input the length:5

Please input the data:1

Please input the data:2

Please input the data:3

Please input the data:4

Please input the data:5

The linked list is:1 2 3 4 5

0

Please input the length:0

The linked list is:

Empty_List

5

1,2,3,4,5

This list is empty.

Please input the length:5

Please input the data:1

Please input the data:2

Please input the data:3

Please input the data:4

Please input the data:5

This list isn't empty.

0

This list is empty.

Please input the length:0

This list is empty.

Clear_List

5

1,2,3,4,5

Please input the length:5

Please input the data:1

Please input the data:2

Please input the data:3

Please input the data:4

Please input the data:5

This list isn't empty.

This list is empty.

-1

Please input the length:-1

This list is empty.

This list is empty.

Length_List

5

1,2,3,4,5

Please input the length:5

Please input the data:1

Please input the data:2

Please input the data:3

Please input the data:4

Please input the data:5

The length of this list is:5

-1

Please input the length:-1

The length of this list is:0

Get_Data

5

1,2,3,4,5

5

Please input the length:5

Please input the data:1

Please input the data:2

Please input the data:3

Please input the data:4

Please input the data:5

The linked list is:5 4 3 2 1

Please input the location of the element you want to get:5

The element is:1

6

Please input the location of the element you want to get:6

get failed

The element is:-858993460

0

Please input the location of the element you want to get:0

get failed

The element is:-858993460

Locate_Data

5

1,2,3,4,5

4

Please input the length:5

Please input the data:1

Please input the data:2

Please input the data:3

Please input the data:4

Please input the data:5

The linked list is:1 2 3 4 5

Please input the element you want to search:4

The location of this element is:4

6

Please input the element you want to search:6

locate failed

The location of this element is:0

Insert_List

5

1,2,3,4,5

6

2

Please input the length:5

Please input the data:1

Please input the data:2

Please input the data:3

Please input the data:4

Please input the data:5

The linked list is:1 2 3 4 5

The element to be inserted is:6

The location of the element to be inserted is:6

The linked list is:1 2 3 4 5 6

The length of this list is:6

6

0

The element to be inserted is:6

The location of the element to be inserted is:0

insert failed

The linked list is:1 2 3 4 5

The length of this list is:5

6

7

The element to be inserted is:6

The location of the element to be inserted is:7

insert failed

The linked list is:1 2 3 4 5

The length of this list is:5

Delete_List

5

1,2,3,4,5

5

Please input the length:5

Please input the data:1

Please input the data:2

Please input the data:3

Please input the data:4

Please input the data:5

The linked list is:1 2 3 4 5

The location of the element to be deleted is:5

The linked list is:1 2 3 4

The length of this list is:4

0

The location of the element to be deleted is:0

delete failed

The linked list is:1 2 3 4 5

The length of this list is:5

6

The location of the element to be deleted is:6

delete failed

The linked list is:1 2 3 4 5

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Binkkkk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值