【数据结构】单链表

前言:

顺序表可以随时存取表中的任意一个元素,它的存储位置可以用一个简单直观的公式表示,但插入和删除操作需要移动大量元素。链式存储线性表时,不需要使用地址的连续存储单元,即不要求逻辑上相邻元素在物理地址上也相邻,它通过“链”建立起数据元素之间的逻辑关系,因此插入和删除元素操作不需要移动元素,而只需要修改指针,但也会失去顺序表可随机存取的优点

1.定义单链表

typedef struct node
{
	int data;
	struct node* next; //指针指向下一个节点
}node,*list;

(1)typedef是重定义struct,这样后面可以写node* s = (node*)malloc(sizeof(node))来定义新节点,否则就得sturct node* s = (sturct node*)malloc(sizeof(sturct node))

(2)括号后面的node表示是对struct node 的重命名,*list实际上是typedef struct node *list(指向node的指针)

node * L 等价于 list L  ,都表示一个指向单链表第一个结点的指针

但是list L 强调这是一个单链表,node*L强调这是一个结点

2.初始化链表

注意头结点不存储数据

bool InitList(list&L) {
	L = (node*)malloc(sizeof(node));
	if (L == NULL)
		return false;
	L->next = NULL;
   return true;
}

3.按位查找

node* getelem(list L, int i)
{
	if (i < 0)
		return NULL;
	node* p;
	int j = 0;
	p = L;
	while (p != NULL && j < i)
	{
		p = p->next;
		j++;
	}
	return p;
}

4.按值查找

node* locate(list L, int e)
{
	node* p = L->next;
	while (p != NULL && p->data != e)
	{
		p = p->next;
	}
	return p;
}

5.按位序插入

bool insert(list& L, int i, int e)//i表示插入的位置,e表示插入的元素
{
	if (i < 1)
		return false;
	node* p;//指针p当前扫描到的结点
	int j = 0;
	p = L;
	while (p != NULL && j < i - 1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
		return false;
	node* s = (node*)malloc(sizeof(node));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

我们可以利用3.按位查找的代码,将代码修改成这样,封装后使代码更加简洁

bool insert(list& L, int i, int e)//i表示插入的位置,e表示插入的元素
{

	node* p = getelem(L, i - 1);
	if (p == NULL)
		return false;
	node* s = (node*)malloc(sizeof(node));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

6.指定结点的前插操作

因为我们不知道目标结点的前一个结点是什么,所以我们有两个办法实现

(1)循坏查找目标结点的前一个结点

(2)在目标结点后增加一个结点s,然后再交换data

代码如下

bool Insert(node* p, int e)
{
	if (p == NULL)
		return false;
	node* s = (node*)malloc(sizeof(node));
	if (s == NULL)
		//内存分配失败
		return false;
	s->next = p->next;
	p->next = s;
	s->data = p->data;
	p->data = e;
	return true;
}

 7.指定结点的删除

本质上是先找到要删除结点的前一个结点,然后“架空”要删除的结点(通过next来实现)

bool Ldelete(list& L, int i, int&e)//用e返回被删除元素的值
{
	node* p = getelem(L, i - 1);//找到要删除的结点p
	if (p == NULL)
		return false;
	if (p->next == NULL)
		return false;
	node* q = p->next;//让q指向被删除的结点
	e = q->data;
	p->next = q->next;//将*q结点从链表中断开
	free(q);
	return true;
}

8.尾插

bool weiinsert(list& L, int i,int e)
{
	node* p = getelem(L, i - 1);
	if (p == NULL)
		return false; 
	node* s = (node*)malloc(sizeof(node));
	s->data = e; 
	s->next = p->next;
	p->next = s; //成功将s连到p之后
	return true;
}

9.打印链表

void Print(list& L) {

	node* p = NULL;
	if (!L) { cout << "此链表为空" << endl; return; }
	p = L->next;
	while (p) 
	{
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}

10.销毁链表

void Destroy(list& L) {

	node* p = L;
	cout << "销毁链表" << endl;
	while (p) {
		L = L->next; //L指向下一个结点
		delete p;   //删除当前结点
		p = L;     //p移向下一个结点
	}
}

相关推荐

  1. 数据结构:

    2024-03-17 17:04:02       33 阅读

最近更新

  1. 如何在vue3中实现动态路由

    2024-03-17 17:04:02       0 阅读
  2. 使用RAGAs评估基于Milvus Cloud的RAG应用

    2024-03-17 17:04:02       0 阅读
  3. electron通信与持久化存储

    2024-03-17 17:04:02       1 阅读
  4. Electron Forge 打包更改打包后图片

    2024-03-17 17:04:02       1 阅读
  5. 【ES】--Elasticsearch的高亮模式

    2024-03-17 17:04:02       1 阅读
  6. JVM专题九:JVM分代知识点梳理

    2024-03-17 17:04:02       1 阅读
  7. 谈谈检测浏览器类型

    2024-03-17 17:04:02       1 阅读
  8. npm 常用命令详解与实践

    2024-03-17 17:04:02       1 阅读

热门阅读

  1. C++中在定义一个宏的时候要注意什么?

    2024-03-17 17:04:02       22 阅读
  2. 突破编程_C++_设计模式(访问者模式)

    2024-03-17 17:04:02       16 阅读
  3. uniapp 实现双击点赞出现特效

    2024-03-17 17:04:02       26 阅读
  4. MongoDB

    MongoDB

    2024-03-17 17:04:02      20 阅读
  5. 栈与队列|239.滑动窗口最大值 (单调队列)

    2024-03-17 17:04:02       21 阅读
  6. 基于AI的测试优化方法

    2024-03-17 17:04:02       21 阅读
  7. 【C++】通讯录管理系统

    2024-03-17 17:04:02       20 阅读
  8. 【Python】实现一个鼠标连点器

    2024-03-17 17:04:02       24 阅读
  9. OGR2GUI

    OGR2GUI

    2024-03-17 17:04:02      20 阅读
  10. Hive调优总结

    2024-03-17 17:04:02       24 阅读