数据结构与算法课程笔记(三)

实验三 线性表的链式存储结构实现

一、实验目的

  1. 掌握线性表的链式存储结构的定义;
  2. 掌握链式存储结构结点的访问方法;
  3. 熟练运用链表的基本操作。

二、实验内容

1. 用linkedlist.h和linkedlist.cpp创建项目,并思考以下问题:
1)观察线性表的各接口函数的函数名,参数表,返回值;明确接口函数的调用方法。思考若要改变线性表元素的类型应如何操作?若添加新的接口函数,需要在哪些文件中进行修改?
答:若要改变线性表元素的类型应更改linkedist.h文件中的typedef char ElemType;若要添加新的接口函数应先在linkedist.h中声明函数,再在linkedist.cpp中编写函数内容
2) 在同一项目中,新建content.cpp文件,在该文件中设计主程序main函数,完成如下功能:
a) 定义管理单链表的头指针L;
b) 初始化单链表L;
c) 在L的头部依次插入 ‘a’, ‘b’, ‘c’, ‘d’ 元素;(可思考如何在尾部插入?)
d) 若L非空,则输出L的长度及L中的元素;
e) 输出L的第三个元素;
f) 输出元素 ‘a’ 的位置;
g) 在L第3个位置上插入元素 'f ',并输出L中元素;
h) 删除第2个元素,输出被删元素的值,并输出L中元素;
i) 删除用户指定的任意元素,若删除成功则输出删除后L中的元素,删除失败给出适当的提示;
j) 释放单链表L。
【参考输出效果】

如需了解程序运行过程,可在循环语句的循环体处设置断点,观察程序运行时,各变量的当前值。

已实现功能的主程序main函数如下:

#include "linkedlist.h"

int main() {
	//a
	LinkNode* L;
	//b
	InitList(L);
	//c
	for (int i = 0; i<4; i++){
		ListInsert(L, 1, 'a'+i);
	}
	//d
	if (!ListEmpty(L)){
		cout << "当前链表长是" << ListLength(L) << ", 表中元素为:";
		TraverseList(L);
	}
	//e
	ElemType data_3;
	Find_pos(L, 3, data_3);
	cout << "第3个元素是 " << data_3 << endl;
	//f
	cout << "a在" << Find_item(L, 'a') << "号位置" << endl;
	//g
	ListInsert(L, 3, 'f');
	cout << "在3号位插入f后,表中元素为:";
	TraverseList(L);
	//h
	ElemType data_2;
	ListDelete(L, 2, data_2);
	cout << "删除第2个元素" << data_2 << "成功。表中元素为:";
	TraverseList(L);
	//i
	ElemType delet_data;
	cin >> delet_data;
	cout << "请输入你想删除的元素:";
	if (ListDelete(L, delet_data)){
		cout << "删除" << delet_data << "成功。表中元素为:";
		TraverseList(L);
	}
	//j
	DestroyList(L);
	return 0;
}

运行结果如图所示:
在这里插入图片描述
3) 总结使用单链表的一般步骤。
答:
1.创建一个单链表结构体
2.初始化单链表的头指针,头指针数据域为空,指针域指向第一个结点
3.对单链表进行基本操作增删查
3.1)增操作实现步骤:
在单链表的头结点之后第一个数据结点之前插入一个新结点,head指向表头结点,head->next表示表头的后继结点,指针 t 指向待插入结点。
3.2)删操作实现步骤:
首先找到被删除位置的前一个结点,并用指针 p 指向删除位置的前驱结点,指针 t 指向被删除的结点;
再将指针p所指结点的指针域修改为t所指结点的后继;
最后释放被删结点t,即delete t
3.3)查操作实现步骤:
设置一个跟踪链表结点的指针p,初始时p指向链表中的第一个结点,然后顺着next域依次指向每个结点。
每指向一个结点就判断其是否等于指定结点,若是,则返回该结点地址。否则继续向后搜索,直到p为NULL ,表示链表中无此元素,返回NULL。

2.假设单链表的数据域为递增有序的整数,设计接口函数:
bool ListInsert_order (LinkNode *L, ElemType item);
向单链表L中插入新的元素item,插入后单链表仍然有序。

linkedlist.h文件:

typedef int ElemType;

linkedlist.cpp文件:
bool ListInsert_order(LinkNode *L, ElemType item)
{
	LinkNode *p = L;
	while (p->next->data < item &&p->next)
		p = p->next;
	LinkNode *t = new LinkNode;
	t->data = item;
	t->next = p->next;
	p->next = t;
	return  true;
}

content.cpp文件:
#include "linkedlist.h"
int main()
{
	LinkNode *L;
	InitList(L);
	ElemType sorted_nums[] = { 3, 6, 9, 12 };
	for (int i = 1; i <= 4; i++)
		ListInsert(L, i, sorted_nums[i - 1]);
	cout << "有序序列:" << endl;
	TraverseList(L);
	ListInsert_order(L, 8);
	cout << "插入8后:" << endl;
	TraverseList(L);
	return 0;
}

【课后练习】
3. 假设单链表的数据域为整数,且数值都不相同,设计接口函数:
bool Delete_max (LinkNode *L, ElemType &item);
把单链表中数据域最大的结点删除,其余结点继续保留。

linkedlist.h文件:

typedef int ElemType;

linkedlist.cpp文件:
bool Delete_max(LinkNode *L, ElemType &item)
{	LinkNode *p = L, *max = L->next,  *pre_to_max = L; 
	while (p->next) {
		if (p->next->data > max->data) {
			max = p->next;
			pre_to_max = p;
		}
		p = p->next;
	}
	if (max != NULL) {
		pre_to_max->next = max->next;
		item = max->data;
		delete max;
		return true;
	}
	return false;
}

content.cpp文件:
#include "linkedlist.h"
int main()
{
	LinkNode *L;
	InitList(L);
	ElemType nums[] = { 9, 18, 10, 13 };
	for (int i = 1; i <= 4; i++)
		ListInsert(L, i, nums[i - 1]);
	cout << "序列为:";
	TraverseList(L);
	ElemType temp;
	if (Delete_max(L, temp)) {
		cout << "删除的最大值为:" << temp << endl;
		cout << "删除后的序列为:";
		TraverseList(L);
	}
	return 0;
}

4.修改项目,以结构体存储学生的两项信息,即:{学号,成绩}:{101,85},{103,90.5},{104,73},{105, 55},并且要让下面的主函数可以正常运行。(此处每对大括号表示一个结构体)
链表结点示意图:
在这里插入图片描述
【提示1】重新设计链表中的元素类型ElemType;
【提示2】修改链表中的相关操作以符合新的元素类型;
【提示3】设计新的接口,删除链表中学号为number的结点。

int main()
{   LinkNode *L;
	InitList(L);
	ElemType A[]={ {101,85}, {103,90.5}, {104,73}, {105,55} };

	for(int i=0; i<4; i++)
		ListInsert(L, i+1, A[i]);
	cout << "学号 成绩" << endl;
	TraverseList(L);

	ListDelete(L, 103);
	cout << "学号 成绩" << endl;
	TraverseList(L);
	DestroyList(L);
	return 0;
}

“linkedlist.h”文件中:

struct Grade
{	
	int id;
	float score;
};
typedef  Grade  ElemType;
typedef struct LNode 
{	ElemType data; 
	struct LNode *next; 
} LinkNode;
//删除链表中学号为number的结点
bool ListDelete (LinkNode *L, int number);

“linkedlist.cpp”文件中,将Find_item函数注释:
//遍历单链表
void TraverseList(LinkNode *L)
{  //L为指向单链表的头指针
	LinkNode *p=L->next;
	while(p)
   { 
        cout<<p->data.id<<"  "<<p->data.score<<endl;
		 p=p->next;
	}
	cout<<endl;
}
//删除链表中学号为number的结点
bool ListDelete (LinkNode *L, int number)
{	
	LinkNode *p=L, *t;  
	while( p->next && p->next->data.id != number){ //查找number的前驱
		p=p->next; 
	}
	if(p->next==NULL){ //查找不成功,退出运行
		cout<<"删除元素不存在"<<endl;
		return false;
	}
	t=p->next;	    //①t为被删除结点
	p->next=t->next; //②删除t的链接关系
	delete t;		   //③释放被删结点
	return true;
}
  • 19
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

青云客_Hugh

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

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

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

打赏作者

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

抵扣说明:

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

余额充值