当前位置: 首页 > article >正文

顺序表和链表(一)

目录

线性表

一、顺序表

<1>顺序表

(1)静态顺序表

(2)动态顺序表-按需申请

<2>链表

(1)单链表

(2)双链表

主程序(test.c)

头文件(DList.h)

调用函数程序(DList.c)


线性表

顺序表、链表、栈、队列、字符串

一、顺序表

连续的物理地址连续(依次)存储数据(数组)

<1>顺序表

(1)静态顺序表
#define N 10
typedef int SLDataType;

struct SeqList
{
	SLDataType a[N];
	SLDataType size;
};

通讯录-C语言-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/Xiaodao12345djs/article/details/142720466?spm=1001.2014.3001.5501这个通讯录就是静态通讯录,缺点很明显,提前开辟内存空间,很可能造成空间浪费

(2)动态顺序表-按需申请

动态顺序表存储数据时会调用函数来开辟动态内存,按需申请,空间利用率较高


#define NAME_MAX 10
#define SEX_MAX 5
#define Address_MAX 30
#define NUMBER_MAX 12
#define MAX 100
 
#define DEFAUL_SZ 3
#define INC_SZ 2
 
//联系人信息
typedef struct Message
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char address[Address_MAX];
	char number[NUMBER_MAX];
}Message;
 
//联系人数量(动态)
typedef struct Contact
{
	Message* list;//指向存放人信息空间
	int num;//存放人信息的个数
	int capacity;//当前通信录最大容量
}Contact;

动态通讯录-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/Xiaodao12345djs/article/details/142732433?spm=1001.2014.3001.5501

<2>链表

(1)单链表

学习链表首先要搞懂结构,物理结构是内存中数据实实在在的变化,为了方便理解,通常用逻辑结构,节点和节点的地址不一定是连续的,所以但单链表的节点中存储下一个节点的地址(指向下一个节点)

单链表的增删查改-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/Xiaodao12345djs/article/details/143064430?spm=1001.2014.3001.5501

 一个数据存一个内存块中,用指针来链接

(2)双链表
主程序(test.c)
#define _CRT_SECURE_NO_WARNINGS 1
#include "DList.h"

int main()
{
	//创建哨兵位及初始化
	ListNode* dlist = ListCreate();
	
	// 双向链表尾插
	ListPushBack(dlist, 1);
	ListPushBack(dlist, 2);
	ListPushBack(dlist, 3);
	ListPushBack(dlist, 4);
	ListPushBack(dlist, 5);
	ListPushBack(dlist, 6);
	//打印
	ListPrint(dlist);

	//尾删
	ListPopBack(dlist);
	ListPrint(dlist);
	
	//头插
	ListPushFront(dlist, 1);
	ListPrint(dlist);
	ListPushFront(dlist, 2);
	ListPrint(dlist);
	ListPushFront(dlist, 3);
	ListPrint(dlist);

	//头删
	ListPopFront(dlist);
	ListPopFront(dlist);
	ListPopFront(dlist);
	ListPrint(dlist);

	//查找
	ListNode* pos = ListFind(dlist, 1);
	//在pos前面插入x
	ListInsert(pos, 2);
	ListPrint(dlist);

	//查找
	pos = ListFind(dlist, 2);
	// 双向链表删除pos位置的节点
	ListErase(pos);
	ListPrint(dlist);

	return 0;
}
头文件(DList.h)
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
	LTDataType _data;
	struct ListNode* _next;
	struct ListNode* _prev;
}ListNode;

// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);
调用函数程序(DList.c)
#define _CRT_SECURE_NO_WARNINGS 1

#include "DList.h"

//创建新节点及申请空间
ListNode* Buynode(LTDataType x)
{
	ListNode* node = (ListNode*)malloc(sizeof(ListNode));
	if (node == NULL)
	{
		perror("node:");
	}
	else
	{
		node->_data = x;
		node->_next = NULL;
		node->_prev = NULL;
	}
	return node;
}

//创建哨兵位及初始化
ListNode* ListCreate()
{
	ListNode* newnode = Buynode(0);
	newnode->_next = newnode;
	newnode->_prev = newnode;
	return newnode;
}

// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
	assert(pHead);
	ListNode* newnode = Buynode(x);
	ListNode* tail = pHead->_prev;
	tail->_next = newnode;
	newnode->_prev = tail;
	newnode->_next = pHead;
	pHead->_prev = newnode;
}

// 双向链表打印
void ListPrint(ListNode* pHead)
{
	assert(pHead);

	ListNode* tail = pHead->_next;
	printf("<= phead ");
	while (tail != pHead)
	{
		printf("<=> %d ", tail->_data);
		tail = tail->_next;
	}
	printf("=>\n");
}

// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
	assert(pHead);
	if (pHead->_next == pHead)
	{
		printf("链表为空,无法删除!!!\n");
		return;
	}
	ListNode* tail = pHead->_prev;
	ListNode* prevnode = tail->_prev;
	prevnode->_next = pHead;
	pHead->_prev = prevnode;
	free(tail);
	tail = NULL;
}

// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
	assert(pHead);

	ListNode* first = pHead->_next;
	ListNode* newnode = Buynode(x);

	newnode->_next = first;
	first->_prev = newnode;
	newnode->_prev = pHead;
	pHead->_next = newnode;
}

// 双向链表头删
void ListPopFront(ListNode* pHead)
{
	assert(pHead);
	if (pHead->_next == pHead)
	{
		printf("链表为空,无法删除!!!\n");
		return;
	}

	ListNode* first = pHead->_next;
	pHead->_next = first->_next;
	first->_next->_prev = pHead;
	free(first);
	first = NULL;

}

// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
	assert(pHead);

	ListNode* scr = pHead->_next;
	while (scr != pHead)
	{
		if (scr->_data == x)
		{
			return scr;
		}
		scr = scr->_next;
	}
	return NULL;
}

// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos);
	ListNode* prev = pos->_prev;
	ListNode* newnode = Buynode(x);

	newnode->_next = pos;
	pos->_prev = newnode;
	prev->_next = newnode;
	newnode->_prev = prev;
}

// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
	assert(pos);

	ListNode* prev = pos->_prev;
	ListNode* next = pos->_next;

	prev->_next = next;
	next->_prev = prev;
	free(pos);
	pos = NULL;
}

 双链表的结构体中定义了两个结构体指针,指向上一个节点和下一个节点,更方便增删查改


http://www.kler.cn/a/376624.html

相关文章:

  • ArcGIS005:ArcMap常用操作101-150例动图演示
  • IMU应用于监测进食
  • ELK的ElasticStack语法
  • 【数据结构-合法括号字符串】力扣1614. 括号的最大嵌套深度
  • 再探“构造函数”(2)友元and内部类
  • WPF+MVVM案例实战(十七)- 自定义字体图标按钮的封装与实现(ABC类)
  • jmeter结合ansible分布式压测--准备工作
  • 深入了解嵌入式硬件设计
  • 视频智能分析平台LiteAIServer入侵检测算法平台部署行人入侵检测算法:智能安防的新利器
  • 钉钉内集成第三方免密登录(Vue+.Net)
  • 定制化视频生成新模范!零样本主体驱动,精确运动控制!复旦阿里等发布DreamVideo-2
  • 算法笔记day10
  • CentOS下Redis简洁安装(无坑版)
  • LocalDate 类常用方法详解(日期时间类)
  • 图文深入介绍Oracle DB link(三)
  • Python世界:自动化办公Word之批量替换文本生成副本
  • C++ 实现俄罗斯方块游戏
  • 贪心算法习题其二【力扣】【算法学习day.19】
  • Selenium自动化测试框架(附教程+文档)
  • Rust 力扣 - 2134. 最少交换次数来组合所有的 1 II
  • 游戏光照的专业知识解析
  • 网络学习/复习3序列化与反序列化/HTTP/HTTPS
  • 了解SQLExpress数据库
  • 文件系统(IO-进程-线程)
  • shodan-4
  • Milvus - GPU 索引类型及其应用场景