数据结构与算法

本文详细介绍了单链表的基本操作,包括链表的初始化、判断空表、销毁、清空、求长度、按值查找、插入和删除等。此外,还提供了头插法和尾插法创建链表的实现,并分析了各操作的时间复杂度。代码示例使用C++编写,便于理解与实践。
摘要由CSDN通过智能技术生成

数据结构
第二章 线性表的链式表现和实现



单链表的基本操作实现

一、基本算法(数据结构——严蔚敏)

添加的简单算法

//若L为空表,则返回1,否则返回0
void ListEmpty(LinkList& L)
{ 
	if (L->next)
		cout << "链表不为空" << endl;
	else
		cout << "链表为空" << endl;
}
//销毁单链表L
Status DestoryList(LinkList& L)
{
	LNode* p; 
	while (L)
	{
		p = L;
		L = L->next;
		delete p;
	}
	return OK;
}
//将L置为空表
Status CleraList(LinkList& L)
{
	LNode* p, * q; 
	p = L->next;
	while (p) 
	{
		q = p->next;
		delete p;
		p = q;
	}
	L->next = NULL; 
	return OK;
}
//求链表长度
int ListLength(LinkList L)
{
	LinkList p;	 
	p = L->next; 
	int i = 0;
	while (p)
	{ 
		i++;
		p = p->next;
	}
	return i;
}

2.6算法:单链表的初始化

Status InitList(LinkList& L)
{
	L = new LNode;
	L->next = NULL; 
	return OK;
}

2.7算法:单链表取值

Status GetElem(LinkList L, int i, ElemType& e)
{
	LinkList p;
	p = L->next;
	int j = 1;		 
	while (p && j < 1)
	{
		p = p->next;
		++j;
	}
	if (!p || j > i)
		return ERROR; 
	e = p->data;	 
	return OK;
}
单链表取值的平均时间复杂度为O(n)。

2.8算法:单链表的按值查找

//链表的按值查找返回地址
LNode* LocateElem(LinkList L, ElemType e)
{
	LNode* p;
	p = L->next;
	while (p && p->data != e)
		p = p->next;
	return p;
}
//按值查找返回序号
Status LocateElem_L(LinkList L, ElemType e)
{
	LinkList p;
	int j = 1;
	p = L->next;
	while (p && p->data != e)
	{
		p = p->next;
		++j;
	}
	if (p)
		return j;
	else
		return 0;
}
查找的时间复杂度为O(n)。

2.9、2.10算法:单链表的插入和删除

//链表插入,在第i个元素之前插入元素e
Status ListInsert(LinkList& L, int i, ElemType e)
{
	LinkList p, s;	int j;
	p = L;	j = 0;
	while (p && j < i - 1)
	{
		p = p->next;	++j;
	} 
	if (!p || j > i + 1)		return ERROR;
	s = new LNode;
	s->data = e;
	s->next = p->next;
	p->next = s; 
	return OK;
}
//单链表的删除
Status LisetDelete(LinkList& L, int i)
{
	LinkList p, s; int j;
	p = L; j = 0;
	while (p && j < i - 1)
	{
		p = p->next;  ++j;
	}
	if(!p||j>i+1)		return ERROR;
	p->next =(p->next)->next;//两种方法
	//s = p->next;
	//p->next =s->next;
	//delete s;
	return OK;
}
线性链表不需要移动元素,只需修改指针,时间复杂度为O(1)。

2.11建立单链表——头插法

//单链表创建,头插法(输入数据顺序与显示数据顺序相反)
LinkList CreatList()
{
	LinkList L, p;
	int i, n;
	InitList(L);
	cout << "构建数据链表:\n";
	cout << "链表中数据个数:\n";
	cin >> n;
	for (i = 0; i < n; i++)
	{
		p = new LNode;
		cout << "请输入数据: " << endl;
		cin >> p->data;
		p->next = L->next;
		L->next = p;
	}
	cout << endl;
	return L;
}
头插法时间复杂度O(n)。

尾插法

//尾插法——元素插在链表尾部
LinkList CreatList_W()
{
	LinkList L, p, r;
	int i, n;
	InitList(L);
	cout << "构建数据链表:\n";
	cout << "链表中数据个数:\n";
	cin >> n;
	r = L;
	for (i = 0; i < n; i++)
	{
		p = new LNode;
		cout << "请输入数据: ";
		cin >> p->data;
		p->next = NULL;
		r->next = p;
		r = p;
	}
	cout << endl;
	return L;
}
尾插法时间复杂度O(n)。

二、详细代码

1.头文件

#pragma once
#include<iostream>
using namespace std;
//函数结果状态代码
#define TURE 1
#define FALSE 0
#define OK  1
#define ERROR 0
#define INFEASIBLE  -1
#define MAXSIZE 100//顺序表可能达到的最大长度
typedef int Status;//status是函数类型,其值是函数结果状态代码
typedef int ElemType;// ElemType是元素的数据类型,想要整体改变元素的数据类型只需改变ElemType前的数据类型即可

typedef struct LNode//声明结点的类型和指向结点的指针类型
{
	ElemType data;//结点的数据域
	struct LNode* next;//结点的指针域
} LNode, * LinkList;//LinkList为指向结构体Lnode的指针类型
//LNode指的是一个结点

2.cpp文件

代码如下(示例):

#include"链式存储.h"
#include<iostream>
using namespace std;
/*各结点有两个域组成
数据域:存储元素数值
指针域:存储直接后继结点的存储位置
结点:数据|指针
链表:n个结点有指针链组成一个链表
无头结点,头指针为空时表示空表:^
有头结点,头指针为空时表示空表:□->□^
头指针->头结点->首元结点(头结点不是数据元素)
*/


//定义链表: LinkList L;
//定义结点指针p: LNode *P; 《==》LinkList p;

Status InitList(LinkList& L);//单链表初始化
LinkList CreatList();
void ShowStudent(LinkList L);
void ListEmpty(LinkList& L);//若L为空表,则返回1,否则返回0
Status DestoryList(LinkList& L);//销毁单链表L
Status CleraList(LinkList& L);//将L置为空表
int ListLength(LinkList L);//求链表长度
Status GetElem(LinkList L, int i, ElemType& e); //获取线性表L中某个数据元素内容,通过变量e返回
LNode* LocateElem(LinkList L, ElemType e);//链表的按值查找返回地址
Status LocateElem_L(LinkList L, ElemType e);//按值查找返回序号
Status ListInsert(LinkList& L, int i, ElemType e);//链表插入,在第i个元素之前插入元素e




//单链表初始化
Status InitList(LinkList& L)
{
	L = new LNode;
	L->next = NULL; 
	return OK;
}
//若L为空表,则返回1,否则返回0
void ListEmpty(LinkList& L)
{ 
	if (L->next)
		cout << "链表不为空" << endl;
	else
		cout << "链表为空" << endl;
}
//销毁单链表L
Status DestoryList(LinkList& L)
{
	LNode* p; 
	while (L)
	{
		p = L;
		L = L->next;
		delete p;
	}
	return OK;
}
//将L置为空表
Status CleraList(LinkList& L)
{
	LNode* p, * q; 
	p = L->next;
	while (p) 
	{
		q = p->next;
		delete p;
		p = q;
	}
	L->next = NULL; 
	return OK;
}
//求链表长度
int ListLength(LinkList L)
{
	LinkList p;	 
	p = L->next; 
	int i = 0;
	while (p)
	{ 
		i++;
		p = p->next;
	}
	return i;
}
//获取线性表L中某个数据元素内容,通过变量e返回
Status GetElem(LinkList L, int i, ElemType& e)
{
	LinkList p;
	p = L->next;
	int j = 1;		 
	while (p && j < 1)
	{
		p = p->next;
		++j;
	}
	if (!p || j > i)
		return ERROR; 
	e = p->data;	 
	return OK;
}
//链表的按值查找返回地址
LNode* LocateElem(LinkList L, ElemType e)
{
	LNode* p;
	p = L->next;
	while (p && p->data != e)
		p = p->next;
	return p;
}
//按值查找返回序号
Status LocateElem_L(LinkList L, ElemType e)
{
	LinkList p;
	int j = 1;
	p = L->next;
	while (p && p->data != e)
	{
		p = p->next;
		++j;
	}
	if (p)
		return j;
	else
		return 0;
}
//链表插入,在第i个元素之前插入元素e
Status ListInsert(LinkList& L, int i, ElemType e)
{
	LinkList p, s;	int j;
	p = L;	j = 0;
	while (p && j < i - 1)
	{
		p = p->next;	++j;
	} 
	if (!p || j > i + 1)		return ERROR;
	s = new LNode;
	s->data = e;
	s->next = p->next;
	p->next = s; 
	return OK;
}
//单链表的删除
Status LisetDelete(LinkList& L, int i)
{
	LinkList p, s; int j;
	p = L; j = 0;
	while (p && j < i - 1)
	{
		p = p->next;  ++j;
	}
	if(!p||j>i+1)		return ERROR;
	p->next =(p->next)->next;//两种方法
	//s = p->next;
	//p->next =s->next;
	//delete s;
	return OK;
}
//单链表创建,头插法
LinkList CreatList()
{
	LinkList L, p;
	int i, n;
	InitList(L);
	cout << "构建数据链表:\n";
	cout << "链表中数据个数:\n";
	cin >> n;
	for (i = 0; i < n; i++)
	{
		p = new LNode;
		cout << "请输入数据: " << endl;
		cin >> p->data;
		p->next = L->next;
		L->next = p;
	}
	cout << endl;
	return L;
}
//显示链表中信息
void ShowStudent(LinkList L)
{
	LinkList p;
	p = L->next;
	while (p)
	{
		cout << "地址:" << p << " 数据:" << p->data << endl;
		p = p->next;
	}
}
//主函数
int main()
{
	LinkList L;
	ElemType e;
	int select = 0;
	InitList(L);

	while (true)
	{
		cout << "请输入您的选择" << endl;
		cout << "0、构建数据链表" << endl;
		cout << "1、显示数据信息" << endl;
		cout << "2、链表数据判空" << endl;
		cout << "3、清空数据链表" << endl;
		cout << "4、数据链表表长" << endl;
		cout << "5、获取链表元素" << endl;
		cout << "6、链表按值查找" << endl;
		cout << "7、链表插入数据" << endl;
		cout << "8、链表删除数据" << endl;
		cout << "99退出系统" << endl;
		cin >> select;
		switch (select)
		{
		case 0:
			L = CreatList();
			system("pause");
			system("cls");
			break;
		case 1:
			ShowStudent(L);
			system("pause");
			system("cls");
			break;
		case 2:
			ListEmpty(L);
			system("pause");
			system("cls");
			break;
		case 3:
			CleraList(L);
			cout << "已将链表清空" << endl;
			system("pause");
			system("cls");
			break;
		case 4:
			int l;
			l = ListLength(L);
			cout << "链表表长为" << l << endl;
			system("pause");
			system("cls");
			break;
		case 5:
			int i;
			cout << "输入数据的位置" << endl;
			cin >> i;
			GetElem(L, i, e);
			cout << "该数据为" << e << endl;
			system("pause");
			system("cls");
			break;
		case 6:
			ElemType a;
			int b;
			ShowStudent(L);
			cout << "输入查找的序号: " << endl;
			cin >> a;
			b = LocateElem_L(L, a);
			cout << "该位置元素为: " << b << endl;
			break;
		case 7:
			ElemType ia;
			int idx;
			cout << "输入插入的位置: " << endl;
			cin >> idx;
			cout << "输入插入的数据: " << endl;
			cin >> ia;
			ListInsert(L, idx, ia);
			break;
		case 8:
			int c;
			cout << "输入删除数据的结点:" << endl;
			cin >> c;
			LisetDelete(L, c);
			break;
		case 99:
			exit(0);
			break;
		default:
			break;
		}
	}
	system("pause");
	return 0;
}


总结

仅用来记录个人学习,有什么问题请在评论区指出!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值