IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 1.2 单链表 -> 正文阅读

[数据结构与算法]1.2 单链表

这一章是单链表的算法分析和代码实现。

单链表的结点数据结构:

typedef struct LNode {
	ElemType data;								//数据域
	struct LNode* next;							//指针域
}LNode, *LinkList ;

主要有以下实现功能的函数:

  1. LinkList List_HeadInsert(LinkList& L) 功能:头插法建立单链表(逆向建立单链表);
    参数:L:链表;
    时间复杂度:O(n);

  2. LinkList List_TailInsert(LinkList& L) 功能:尾插法建立单链表(正向建立单链表);
    参数:L:链表;
    时间复杂度:O(n);

  3. LNode* GetElem(LinkList L, int i) 功能:按序号查找结点;
    参数:L:链表 , i:要查找的结点的位置;
    时间复杂度:O(n);

  4. LNode* LocateElem(LinkList L, ElemType e) 功能:按值查找结点(查找第一次出现的);
    参数:L:链表,e:要查找的结点的值;
    时间复杂度:O(n);

  5. bool LNodeInsert(LinkList &L,int i,ElemType e) 功能:插入一个结点;
    参数:L:链表 ,i:插入的位置,e:插入结点的值
    时间复杂度:O(n);

  6. bool LNodeDelete(LinkList &L, int i) 功能:删除一个结点;
    参数:L:链表,i:删除结点的位置;
    时间复杂度:O(n);

  7. bool LNodeRevise(LinkList& L, int i, ElemType e) 功能:修改一个结点的值;
    参数:L:链表,i:要修改的结点位置,e:要改成的值;
    时间复杂度:O(n);

  8. int LinkLength(LinkList L) 功能:求表长;
    参数:L:链表;
    时间复杂度:O(n);

  9. void PrintList(LinkList L) 功能:输出所有结点的值;
    参数:L:链表;
    时间复杂度:O(n);

可能理解困难的地方:
关于头插法和尾插法:头插法是把每次插入的结点都放到头结点后一位;而尾插法有尾结点指针,每次插入新结点到尾结点后面,然后把尾结点指针移到新插入的结点上。所以用头插法建立的链表和输入的顺序倒序,而尾插法是顺序的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
完整代码:

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

#define ElemType int

/*--------------------------------------------数据结构部分--------------------------------------------*/
/*单链表的数据结构*/
typedef struct LNode {
	ElemType data;								//数据域
	struct LNode* next;							//指针域
}LNode, *LinkList ;

/*初始化链表*/
void InitList(LinkList& L) {
	L = (LinkList)malloc(sizeof(LNode));		//创建头结点
	L->next = NULL;								//初始为空链表
}

/*头插法建立单链表(逆向建立单链表)*/
LinkList List_HeadInsert(LinkList& L) {
	LNode* s,* p;								//s是创建的结点的指针
	int x;
	InitList(L);								//初始化链表
	p = L;
	scanf("%d", &x);							//输入结点的值
	while (x!=9999)								//输入9999结束
	{
		s = (LNode*)malloc(sizeof(LNode));		//创建新结点
		//s = new LNode							//c++可以new
		s->data = x;
		s->next = p->next;						//将新结点插入表中,s->next指向头结点外的第一个结点
		p->next = s;
		scanf("%d", &x);
	}
	return L;
}

/*尾插法建立单链表(正向建立单链表)*/
LinkList List_TailInsert(LinkList& L) {
	int x;
	InitList(L);
	LNode* s, * r = L;						//r为表尾指针
	scanf("%d", &x);
	while (x!=9999)
	{
		s = new LNode;
		s->data = x;
		r->next = s;						//把新结点s添加到表尾r
		r = s;								//r指向新的表尾结点
		scanf("%d", &x);
	}
	r->next = NULL;							//尾结点指针置空
	return L;
}

/*按序号查找结点*/
LNode* GetElem(LinkList L, int i) {
	int j = 1;								//计数,初始为1
	LNode* p = L->next;						//头结点赋值给p
	if (i == 0)								//若i == 0 则返回头结点
		return L;							
	if (i < 1)								//若i无效则返回NULL
		return NULL;
	while (p && j<i)						//从第一个结点开始找,找到第i个结点
	{										//在p == NULL(表遍历结束)或j == i(已找到第i个结点)时跳出循环
		p = p->next;
		j++;
	}
	return p;								//返回第i个结点的指针,若i大于表长返回NULL
}

/*按值查找结点*/
LNode* LocateElem(LinkList L, ElemType e) {
	LNode* p = L->next;
	while (p != NULL && p->data != e)		//从第1个结点开始查找data为e的结点
	{
		p = p->next;						//移动结点指针
	}
	return p;								//找到后返回该节点的指针,否则返回NULL
}

/*插入结点*/
bool LNodeInsert(LinkList &L,int i,ElemType e) {
	LNode* s;
	LinkList p = L;
	p = GetElem(L, i - 1);					//查找插入位置的前驱结点
	if (!p)
		return false;
	s = new LNode;
	s->data = e;
	s->next = p->next;						//s->next指向原来p的下一个结点
	p->next = s;							//p->next指向新增的s结点
	return true;
}

/*删除结点*/
bool LNodeDelete(LinkList &L, int i) {
	LNode* q;
	LinkList p = L;
	p = GetElem(L, i - 1);					//查找删除位置的前驱结点
	if (!p)
		return false;
	q = p->next;							//q指向被删除结点
	p->next = q->next;						//将*q结点从链中断开
	free(q);								//释放结点的存储空间
	return true;
}

/*求表长*/
int LinkLength(LinkList L) {
	LNode* p = L->next;						//头节点不存放数据,不算长度
	int sum = 0;
	while (p)
	{
		p = p->next;						//移动结点指针
		sum++;
	}
	return sum;								//返回表长
}

/*修改节点*/
bool LNodeRevise(LinkList& L, int i, ElemType e) {
	LinkList p = L;
	p = GetElem(L, i);						//拿到要修改的结点
	if (!p || i == 0)						//结点不能为空,不能修改头结点
		return false;
	p->data = e;							//修改结点的值
	return true;
}

/*--------------------------------------------下面是功能函数--------------------------------------------*/
/*插入结点的功能*/
void Insert(LinkList& L) {
	int location;
	ElemType elem;
	printf("输入要插入的元素:");
	scanf("%d", &elem);
	printf("要插入的位置:");
	scanf("%d", &location);
	if (LNodeInsert(L, location, elem))
		printf("插入成功\n");
	else
		printf("插入失败\n");
}

/*删除结点的功能*/
void Delete(LinkList& L) {
	int location;
	printf("输入要删除的元素的位置:");
	scanf("%d", &location);
	if (LNodeDelete(L, location))
		printf("删除成功\n");
	else
		printf("删除失败\n");
}

/*修改结点的功能*/
void Revise(LinkList& L) {
	int i;
	ElemType e;
	printf("输入要修改的位置:");
	scanf("%d", &i);
	printf("修改为:");
	scanf("%d", &e);
	if (LNodeRevise(L, i, e))
		printf("修改成功\n");
	else
		printf("修改失败\n");
}

void Search(LinkList L) {
	int searchChoice;
	printf("(1)按位查找\n");
	printf("(2)按值查找\n");
	printf("选择查找功能:\n");
	scanf("%d", &searchChoice);
	int i;
	ElemType e;
	LNode* p;
	switch (searchChoice)
	{
		case(1):
			printf("输入要查找的节点位置:");
			scanf("%d", &i);
			p = GetElem(L, i);
			if (p && i != 0)					//查找的结点不能为空,也不能查找头结点的值
				printf("第%d个结点的值为%d\n", i, p->data);
			else
				printf("查找失败\n");
			break;
		case(2):
			printf("输入要查找的结点的值:");
			scanf("%d", &e);
			p = LocateElem(L, e);
			if (p)
				printf("找到该元素,查找成功\n");
			else
				printf("找不到该元素,查找失败\n");
			break;
		default:
			break;
	}
}

void PrintList(LinkList L) {
	LinkList p = L->next;					 //头结点无数据不输出
	if (!p)
		printf("表空\n");
	else {
		printf("链表数据:\n");
		while (p)
		{
			printf("%d  ", p->data);
			p = p->next;
		}
		printf("\n共%d个元素\n", LinkLength(L));
	}
}

void menu() {
	printf("\n\n");
	printf("----------①前插法建立链表----------\n");
	printf("----------②后插法建立链表----------\n");
	printf("----------③   插入结点   ----------\n");
	printf("----------④   删除结点   ----------\n");
	printf("----------⑤   修改结点   ----------\n");
	printf("----------⑥   查找结点   ----------\n");
	printf("----------⑦    打印表    ----------\n");
	printf("按“0”退出\n");
	printf("\n\n");
}

int main() {
	LinkList L;
	int choice;
	do
	{
		menu();
		scanf("%d", &choice);
		switch (choice)
		{
			case(1):
				printf("输入每个元素的值(输入9999停止建表)\n");
				List_HeadInsert(L);
				break;
			case(2):
				printf("输入每个元素的值(输入9999停止建表)\n");
				List_TailInsert(L);
				break;
			case(3):
				Insert(L);
				break;
			case(4):
				Delete(L);
				break;
			case(5):
				Revise(L);
				break;
			case(6):
				Search(L);
				break;
			case(7):
				PrintList(L);
				break;
			default:
				break;
		}
	} while (choice!=0);
	return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-25 12:27:44  更:2021-08-25 12:29:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:48:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码