各种顺序表和链表的实现代码

news2024/11/25 5:02:49

目录

一、什么是线性表

二、顺序表

2.1什么是顺序表

2.2静态顺序表的代码实现

2.3动态顺序表的代码实现

三、链表

3.1什么是链表

3.2不带头单向不循环链表的代码实现

3.3带头双向循环链表的代码实现

四、顺序表和链表的区别


一、什么是线性表

线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常的线性表有:链表、顺序表、栈、队列、字符串……

线性表在逻辑上是线性结构,也就是连续的一条直线。但是在物理结构上并不是一定连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

二、顺序表

2.1什么是顺序表

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

2.2静态顺序表的代码实现

//SeqList.h头文件

#pragma once

#define MAX_SIZE 10

typedef int SQDataType;

#include <stdio.h>
#include <string.h>
typedef struct SeqList
{
	SQDataType a[MAX_SIZE];
	int size;
}SL;



void SeqListInit(SL* ps);

void SeqListPushBack(SL* ps, SQDataType x);
void SeqListPushFront(SL* ps, SQDataType x);
void SeqListPopBack(SL* ps);
void SeqListPopFront(SL* ps);


void SeqListPrint(SL* ps);
//SeqList.c文件


#define _CRT_SECURE_NO_WARNINGS 1

#include "SeqList.h"

//顺序表的初始化
void SeqListInit(SL* ps)
{
	memset(ps->a, 0, sizeof(SQDataType) * MAX_SIZE);
	ps->size = 0;
}

//尾插
void SeqListPushBack(SL* ps, SQDataType x)
{
	if (ps->size >= MAX_SIZE)
	{
		printf("SeqList is Full\n");
	}
	ps->a[ps->size] = x;
	ps->size++;
}

//打印
void SeqListPrint(SL* ps)
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}



//……
//其他的接口函数可以自己实现

2.3动态顺序表的代码实现

//SeqList.h文件


#pragma once


#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <assert.h>

typedef int DatatType;
typedef struct SeqList
{
	DatatType* data;
	int size;
	int capacity;
}SeqList;


// 对数据的管理:增删查改 
void SeqListInit(SeqList* ps);
void SeqListDestroy(SeqList* ps);

void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, DatatType x);
void SeqListPushFront(SeqList* ps, DatatType x);
void SeqListPopFront(SeqList* ps);
void SeqListPopBack(SeqList* ps);

// 顺序表查找
int SeqListFind(SeqList* ps, DatatType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, DatatType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);
//SeqList.c文件


#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
//初始化
void SeqListInit(SeqList* ps)
{
	assert(ps);
	ps->data = (DatatType*)malloc(sizeof(DatatType) * 4);
	if (NULL == ps->data)
	{
		perror("malloc fail");
		return;
	}
	ps->size = 0;
	ps->capacity = 4;
}

//销毁
void SeqListDestroy(SeqList* ps)
{
	assert(ps);
	free(ps->data);
	ps->data = NULL;
	ps->size = 0;
	ps->capacity = 0;
}
//打印
void SeqListPrint(SeqList* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->data[i]);
	}
	printf("\n");
}

void CheckCapacity(SeqList* ps)
{
	assert(ps);
	if (ps->size == ps->capacity)
	{
		DatatType* tmp = (DatatType*)realloc(ps->data, sizeof(DatatType) * 2 * ps->capacity);
		if (NULL == tmp)
		{
			perror("realloc fail");
			return;
		}
		ps->data = tmp;
		ps->capacity *= 2;
	}
}

//尾插
void SeqListPushBack(SeqList* ps, DatatType x)
{
	/*CheckCapacity(ps);
	ps->data[ps->size] = x;
	ps->size++;*/
	SeqListInsert(ps, ps->size, x);

}
//头插
void SeqListPushFront(SeqList* ps, DatatType x)
{
	SeqListInsert(ps, 0, x);
}
//头删
void SeqListPopFront(SeqList* ps)
{
	SeqListErase(ps, 0);

}
//尾删
void SeqListPopBack(SeqList* ps)
{
	SeqListErase(ps, ps->size - 1);
}

// 顺序表查找
int SeqListFind(SeqList* ps, DatatType x)
{
	assert(ps);
	//找到返回下标,没有找到返回-1
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->data[i] == x)
		{
			return i;
		}
	}
	return -1;
}
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, DatatType x)
{
	assert(pos >= 0 && pos <= ps->size);
	CheckCapacity(ps);
	int end = ps->size - 1;

	//往后移元素
	while (end >= pos)
	{
		ps->data[end + 1] = ps->data[end];
		end--;
	}

	//插入
	ps->data[pos] = x;
	ps->size++;
}

// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos)
{	
	assert(pos >= 0 && pos < ps->size);
	int start = pos;
	while (start < ps->size - 1)
	{
		ps->data[start] = ps->data[start + 1];
		start++;
	}
	ps->size--;
}

三、链表

3.1什么是链表

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

3.2不带头单向不循环链表的代码实现

 

//SList.h文件

#pragma once


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

typedef int DataType;

typedef struct SListNode
{
	DataType data;
	struct SListNode* next;
}SLTNode;


//头插、尾插、头删、尾删
void SLPushFront(SLTNode** pphead, DataType x);
void SLPushBack(SLTNode** pphead, DataType x);
void SLPopFront(SLTNode** pphead);
void SLPopBack(SLTNode** pphead);
//查找
SLTNode* SLFind(SLTNode** pphead, DataType x);

//修改
void SLModify(SLTNode** pphead, DataType x, int pos);
//打印
void SLPrint(SLTNode** pphead);
//销毁
void SLDestory(SLTNode** pphead);


// 在pos之前插入
void SLInsert(SLTNode** pphead, SLTNode* pos, DataType x);

// 在pos之后插入
void SLInsertAfter(SLTNode* pos, DataType x);

// 删除pos位置的值
void SLErase(SLTNode** pphead, SLTNode* pos);

//删除pos位置后面的值
void SLEraseAfter(SLTNode* pos);
//SList.c文件


#define _CRT_SECURE_NO_WARNINGS 1


#include "SList.h"

SLTNode* BuyNode(DataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (NULL == newnode)
	{
		perror("malloc fail");
		return NULL;
	}
	else
	{
		newnode->data = x;
		newnode->next = NULL;
	}
	return newnode;
}

//头插、尾插、头删、尾删
void SLPushFront(SLTNode** pphead, DataType x)
{
	assert(pphead);
	SLTNode* newnode = BuyNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
}

void SLPushBack(SLTNode** pphead, DataType x)
{
	SLTNode* newnode = BuyNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next)
		{
			tail = tail->next;
		}
		tail->next = newnode;

	}
}
void SLPopFront(SLTNode** pphead)
{
	//没有节点
	assert(pphead);
	assert(*pphead);
	//有一个节点
	//if ((*pphead)->next == NULL)
	//{
	//	free(*pphead);
	//	*pphead = NULL;
	//}
	有多个节点
	//else
	//{
	//	SLTNode* del = *pphead;
	//	*pphead = del->next;
	//	free(del);
	//	del = NULL;
	//}
	SLTNode* del = *pphead;
	*pphead = del->next;
	free(del);
	del = NULL;
}
void SLPopBack(SLTNode** pphead)
{
	//没有节点
	assert(*pphead);
	//有一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}

	//有多个节点
	else
	{
		SLTNode* tail = *pphead;
		SLTNode* prev = NULL;

		while (tail->next)
		{
			prev = tail;
			tail = tail->next;
		}
		prev->next = NULL;
		free(tail);
	}
}

//查找
SLTNode* SLFind(SLTNode** pphead, DataType x)
{
	SLTNode* cur = *pphead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	printf("没有此节点\n");
	return NULL;
}

//修改
void SLModify(SLTNode** pphead, DataType x, int pos)
{
	assert(*pphead);
	SLTNode* cur = *pphead;
	while (cur && pos > 0)
	{
		cur = cur->next;
		pos--;
	}
	cur->data = x;
}

//打印
void SLPrint(SLTNode** pphead)
{
	SLTNode* cur = *pphead;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

//销毁
void SLDestory(SLTNode** pphead)
{
	SLTNode* next = ( * pphead)->next;
	while (*pphead)
	{
		free(*pphead);
		*pphead = next;
		if(next)
			next = next->next;
	}
	*pphead = NULL;
	next = NULL;
}


// 在pos之前插入
void SLInsert(SLTNode** pphead, SLTNode* pos, DataType x)
{
	assert(pos);
	SLTNode* newnode = BuyNode(x);
	SLTNode* cur = *pphead;
	if (*pphead == pos)
	{
		newnode->next = pos;
		*pphead = newnode;
	}
	else
	{
		while (cur->next != pos)
		{
			cur = cur->next;
		}
		cur->next = newnode;
		newnode->next = pos;
	}
}

// 在pos之后插入
void SLInsertAfter(SLTNode* pos, DataType x)
{
	SLTNode* newnode = BuyNode(x);
	SLTNode* next = pos->next;
	newnode->next = next;
	pos->next = newnode;
}

// 删除pos位置的值
void SLErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	SLTNode* prev = *pphead;
	if (pos == *pphead)
	{
		SLPopFront(pphead);
		/**pphead = pos->next;
		free(pos);
		pos = NULL;*/
	}
	else
	{
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}


//删除pos位置后面的值
void SLEraseAfter(SLTNode* pos)
{
	assert(pos->next);
	assert(pos);
	SLTNode* next = pos->next;
	pos->next = next->next;
	free(next);
	next = NULL;
}

3.3带头双向循环链表的代码实现

//List.h文件


#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
typedef int DataType;
typedef struct ListNode
{
	DataType data;
	struct ListNode* next;
	struct ListNode* prev;
}ListNode;

//初始化链表
void ListInit(ListNode* phead);

//尾插、尾删
void ListPushBack(ListNode* phead, DataType x);
void ListPopBack(ListNode* phead);

//头插、头删
void ListPushFront(ListNode* phead, DataType x);
void ListPopFront(ListNode* phead);

//打印
void ListPrint(ListNode* phead);

//查找
ListNode* ListFind(ListNode* phead, DataType x);

//判空
bool ListEmpty(ListNode* phead);

//pos位置之前插入
void ListInsert(ListNode* pos, DataType x);

//删除pos节点
void ListErase(ListNode* pos);

//销毁
void ListDestroy(ListNode* phead);
//List.c文件


#define _CRT_SECURE_NO_WARNINGS 1

#include "List.h"

//初始化
void ListInit(ListNode* phead)
{
	phead->next = phead;
	phead->prev = phead;
	phead->data = -1;
}

//malloc一个节点
ListNode* BuyNode(DataType x)
{
	ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
	if (newNode == NULL)
	{
		perror("malloc fail!\n");
		return NULL;
	}
	newNode->data = x;
	newNode->next = NULL;
	newNode->prev = NULL;
	return newNode;
}

//尾插
void ListPushBack(ListNode* phead, DataType x)
{
	assert(phead);

	ListNode* tail = phead->prev;
	ListNode* newNode = BuyNode(x);
	tail->next = newNode;
	newNode->prev = tail;
	newNode->next = phead;
	phead->prev = newNode;
}

//尾删
void ListPopBack(ListNode* phead)
{
	assert(phead);
	assert(phead->next != phead);
	ListNode* tail = phead->prev;
	ListNode* prev_tail = tail->prev;
	prev_tail->next = phead;
	phead->prev = prev_tail;
	free(tail);
	tail = NULL;
}

//头插
void ListPushFront(ListNode* phead, DataType x)
{
	assert(phead);
	ListNode* newnode = BuyNode(x);
	ListNode* first = phead->next;

	phead->next = newnode;
	newnode->prev = phead;
	newnode->next = first;
	first->prev = newnode;
}

//头删
void ListPopFront(ListNode* phead)
{
	assert(phead);
	//判空
	assert(phead->next != phead);
	ListNode* del = phead->next;
	phead->next = del->next;
	del->next->prev = phead;
	free(del);
	del = NULL;	
}

//打印
void ListPrint(ListNode* phead)
{
	assert(phead);
	ListNode* cur = phead->next;
	printf("guard<==>");
	while (cur != phead)
	{
		printf("%d<==>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

//查找
ListNode* ListFind(ListNode* phead, DataType x)
{
	assert(phead);
	ListNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//判空
bool ListEmpty(ListNode* phead)
{
	return phead->next == phead;
}

//在POS位置前插入
void ListInsert(ListNode* pos, DataType x)
{
	assert(pos);
	ListNode* prev = pos->prev;
	ListNode* newnode = BuyNode(x);

	prev->next = newnode;
	newnode->prev = prev;
	newnode->next = pos;
	pos->prev = newnode;
}

//删除POS位置的节点
void ListErase(ListNode* pos)
{
	assert(pos);
	ListNode* posPrev = pos->prev;
	ListNode* posNext = pos->next;

	posPrev->next = posNext;
	posNext->prev = posPrev;

	free(pos);
}

//销毁
void ListDestroy(ListNode* phead)
{
	assert(phead);
	ListNode* cur = phead->next;
	while (cur != phead)
	{
		ListNode* next = cur->next;
		free(cur);
		cur = next;
	}
}

四、顺序表和链表的区别

不同点顺序表链表
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持:O(1)不支持:O(N)
任意位置插入或者删除元素可能需要搬移元素,效率低O(N)只需要修改指针指向
插入动态顺序表,空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁
缓存利用率

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/518526.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(十五)数据编辑——图形编辑①

数据编辑——图形编辑① 数据编辑包括几何数据和属性数据的编辑。几何数据的编辑主要是针对图形的操作&#xff0c;即图形编辑&#xff0c;包括平行线复制、缓冲区生成、镜面反射、图层合并、结点操作、拓扑编辑等。属性编辑主要包括图层要素属性的添加、删除、修改、复制、粘…

谷歌落子,我们对中国大模型的期待应该是什么?

对中国大模型厂商而言&#xff0c;市场期待的&#xff0c;也恰是这些真正可落地的应用和实践。这些实践可以在社交&#xff0c;在电商&#xff0c;在低代码&#xff0c;在供应链&#xff0c;也更可以在一个个中国产业数字化转型的新洼地。 作者|思杭 皮爷 出品|产业家 在微软G…

裸辞5个月,面试了37家公司,终于.....

上半年裁员&#xff0c;下半年裸辞&#xff0c;有不少人高呼裸辞后躺平真的好快乐&#xff01;但也有很多人&#xff0c;裸辞后的生活五味杂陈。 面试37次终于找到心仪工作 因为工作压力大、领导PUA等各种原因&#xff0c;今年2月下旬我从一家互联网小厂裸辞&#xff0c;没想…

执行增删改查时的结果处理

查询最终走到PreparedStatementHandler类的query方法&#xff0c;执行查询后调用DefaultResultSetHandler类的handleResultSets方法 1.处理返回的普通实体类 DefaultResultSetHandler类的handleResultSets方法 继续本类的handleResultSet方法 通过 handleRowValues 方法来…

设计一个可靠的自动化测试框架需要考虑哪些问题呢?

随着软件开发的日益普及&#xff0c;自动化测试框架逐渐成为了保障软件质量的必备工具。然而&#xff0c;如何设计一个可靠的自动化测试框架并不是一件简单的事情&#xff0c;需要考虑多方面的问题。本文将从需求分析、架构设计、测试用例编写等多个角度&#xff0c;介绍设计一…

【SpringMVC】| SpringMVC拦截器

目录 一&#xff1a;SpringMVC拦截器 1. 拦截器介绍 2. HandlerInterceptor接口分析 3. 自定义拦截器实现权限验证 一&#xff1a;SpringMVC拦截器 SpringMVC 中的 Interceptor 拦截器&#xff0c;它的主要作用是拦截指定的用户请求&#xff0c;并进行相应的预处理与后处理…

C++面向对象(黑马程序员)

内存分区模型 #include<iostream> using namespace std;//栈区数据注意事项&#xff1a;不要返回局部变量的地址 //栈区的数据由编译器管理开辟和释放int* func(int b) //形参数据也会放在栈区 {b 100;int a 10; //局部变量存放在栈区&#xff0c;栈区的数据在函数执…

Qt创建项目 No suitable kits found.

最近因为要写.net6项目&#xff0c;而更新了Visual Studio&#xff0c;后来再使用Qt的时候发现不能编译了。 调整后&#xff0c;发现新建项目显示“No suitable kits found”错误。 网上也看了很多的解决方案&#xff0c;但都不得要领&#xff0c;也都没有解决。 ----------…

Java-Redis持久化之AOF操作

Java-Redis持久化之AOF操作 1.AOF(append only file)2.请你用自己的话说一说 AOF的过程?3.配置如何开启AOF操作4.AOF的优点和缺点: 1.AOF(append only file) 将我们所有的命令都记录下来保存到文件&#xff0c;恢复的时候把这个文件都执行一遍。 2.请你用自己的话说一说 AOF…

【Vue】学习笔记-全局事件总线

全局事件总线(GlobalEventBus) 一种可以在任意组件通信的方式&#xff0c;本质上就是一个对象&#xff0c;它必须满足以下条件 所有的组件对象都必须能看见他这个对象必须能够使用$ on $ emit $ off方法取绑定、触发和解绑事件 使用步骤 定义全局事件总线 //创建VUE new V…

WPF中的用户控件和自定义控件详解

总目录 文章目录 总目录一、什么是用户控件和自定义控件1 用户控件和自定义控件2 相关知识点2 用户控件和自定义控件的适用场景 二、用户控件的使用1.通过依赖属性和路由事件封装用户控件的案例2.通过依赖属性命令依赖属性封装用户控件的案例3.只对外提供属性不对外提供操作的用…

USBCAN卡和台达AS228T通信

AS228R 如图 A.把CAN卡固定上 B.接一个120欧的终端电阻 C.把来可的USBCAN卡的CANH和CANL分别接入AS228R的CANH和CANL. CAN 接口及网络拓扑 10.2.4.1 CAN 网络实体信号的定义及数据格式 CAN 信号为差分信号&#xff0c;信号电压为 CAN和 CAN-之间的电压差&#xff0c;CAN 和…

怎样删除hao123(浏览器首页被篡改了)

有时候我们打开浏览器发现首页被hao123 ,或者2345 这些浏览器给篡改了 或者打开的时候直接打开2个.这个时候想要删除它们,其他它们本身就是网页的,没有应用 在卸载的地方就不用了,它们就嵌套你的浏览器里面,打开的时候启动了他们, 下面说下方法 1 查看浏览器在什么方法下载…

第3天学习Docker-Docker部署常见应用(MySQL、Tomcat、Nginx、Redis、Centos)

前提须知&#xff1a; &#xff08;1&#xff09;搜索镜像命令 格式&#xff1a;docker search 镜像名 &#xff08;2&#xff09;设置Docker镜像加速器 详见文章&#xff1a;Docker设置ustc的镜像源&#xff08;镜像加速器&#xff09; 1、部署MySQL 拉取镜像&#xff08;这…

Radius:针对Rollup生态的Trustless Shared Sequencing层

1. 引言 前序博客&#xff1a; Rollup去中心化Rollup DecentralizationAztec 征集 Rollup Sequencer去中心化提案 Rollup中单一中心化sequencer的问题在于&#xff1a; 审查MEV extraction MEV extraction的问题不在于中心化本身&#xff0c;而在于sequencer具有操纵交易顺…

CN学术期刊《西部素质教育》简介及投稿邮箱

《西部素质教育》&#xff08;半月刊&#xff09;创刊于2015年&#xff0c;是由青海人民出版社有限责任公司主管/主办的教育类学术期刊&#xff0c;本刊恪守“追踪教育研究前沿&#xff0c;关注教育实践热点&#xff0c;探索创新教育理念&#xff0c;传播教育教学信息&#xff…

测试外包干了4年,我废了...

这是来自一位粉丝的投稿内容如下&#xff1a; 先说一下自己的个人情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某外包公司&#xff0c;干了接近4年的软件测试外包工作&#xff0c;马上2023年秋招了&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在…

JOSEF 约瑟 JZ-7Y-E/06静态中间继电器 拓展端子 接线牢固

​ JZ-7Y-E/06静态中间继电器品牌:JOSEF约瑟名称:静态中间继电器型号:JZ-7Y-E/06额定电压:6220VDC&#xff1b;6380VAC触点容量:10A/250V10A/220VDC功率消耗:≤6W JZ-7Y-E/06静态中间继电器 系列型号&#xff1a; JZ-7Y-E/60静态中间继电器&#xff1b; JZ-7J-E/60…

Spring ( 一 ) 依赖耦合

1.依赖耦合及解耦 1.1.从<<西游记>>说起 1.1.1.主角介绍 使用 Java 语言中编写一个 HouWang 猴王类 // 猴王 public class HouWang {// 成员变量private String mingZi;// 无参构造方法public HouWang() {System.out.println("石破天惊");}// 有参数构…

知识推理——TransE(知识表示、知识嵌入)

记录一下学习TransE的笔记~ 最后更新时间&#xff1a;20230512 1.要解决的问题 &#xff08;1&#xff09;以往的模型&#xff08;Bayesian clustering和energy-based&#xff09;关注于增强模型的表达能力和普遍性&#xff0c;但却增加了模型的复杂性及计算消耗。 &#xff0…