【数据结构】C语言实现双向链表(带头尾指针,非循环链表)

C语言详解双向链表的基本操作 双链表的定义与接口函数 定义双链表 接口函数 详解接口函数的实现 创建新节点(BuyLTNode) 初始化双链表(ListInit) 双向链表打印(ListPrint) 双链表查找(ListFind) 双链表销毁(ListDestory) 1、双链表pos位置之前插入(ListInsert) 2、双链表删除pos位置(ListEarse) 3、双向链表尾插(ListPushBack) 4、双向链表头插(ListPushFront) 5、双链表头删(ListPopF....... 阅读详情

DLinkList.h

#pragma once

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


typedef char DLinkType;

//C语言双向链表

typedef struct DLinkNode{

	 DLinkType data;
	 struct DLinkNode* _next;
	 struct DLinkNode* _prev;

}DLinkNode;

typedef struct DLinkList{

	DLinkNode* head;
	DLinkNode* tail;
	int size;

}DLinkList;

//创建一个结点
DLinkNode* CreatNewNode(DLinkType value);
//释放一个结点
void DestoryNode(DLinkNode** node);
//初始化双向链表
DLinkList* InitDLinkList();
//判断链表是否为空
int DLinkListEmpty(DLinkList* plist);
//尾插一个元素
DLinkList* DLinkListPushBack(DLinkList* plist, DLinkType value);
//打印整个链表
void PrintChar(DLinkList* plist, char* msg);
//尾删一个元素
void DLinkListPopBack(DLinkList* plist);
//头插一个元素
void DLinkListPushFront(DLinkList* plist, DLinkType value);
//头删一个元素
void DLinkListPopFront(DLinkList* plist);
//查找某个元素
DLinkNode* DLinkListFind(DLinkList* plist, DLinkType to_find);
//往指定位置之前插入一个元素
void DLinkListInsert(DLinkList* plist,DLinkNode* pos, DLinkType value);
//往指定位置之后插入一个元素
void DLinkListInsertAfter(DLinkList* plist, DLinkNode* pos, DLinkType value);
//删除指定位置的元素
void DLinkListErase(DLinkList* plist, DLinkNode* pos);
//删除指定值的元素
void DLinkListRemove(DLinkList* plist, DLinkType to_delete);
//删除所有指定值的元素
void DLinkListRemoveAll(DLinkList* plist, DLinkType to_delete);

//删除一个链表的所有元素
void DLinkListClear(DLinkList* plist);


DLinkList.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"DLinkList.h"

//创建一个结点
DLinkNode* CreatNewNode(DLinkType value) {

	DLinkNode* Node = (DLinkNode*)malloc(sizeof(DLinkNode));
	if (Node != NULL) {

		Node->data = value;
		Node->_next = NULL;
		Node->_prev = NULL;

	}

	return Node;
}

//释放一个结点
void DestoryNode(DLinkNode** node) {

	if (node == NULL) {
		//非法输入
		return;
	}
	if (*node == NULL) {
		//结点传入错误
		return;
	}
	free(*node);
	*node = NULL;

}

//初始化双向链表
DLinkList* InitDLinkList() {

	DLinkList* plist = (DLinkList*)malloc(sizeof(DLinkList));
	plist->head = CreatNewNode('0');

	if (plist != NULL) {

		if (plist->head != NULL) {

			plist->head = plist->head;
			plist->tail = plist->head;
			plist->size = 0;

		}
		else {
			return NULL;
		}
	}
	return plist;
}

//判断链表是否为空
int DLinkListEmpty(DLinkList* plist) {

	if (plist == NULL) {
		return;
	}
	if (plist->tail == plist->head &&
		plist->size == 0) {

		return 1;

	}
	return 0;

}
//尾插一个元素
DLinkList* DLinkListPushBack(DLinkList* plist, DLinkType value) {

	if (plist->head == NULL) {
		return;
	}
	DLinkNode* InsertNode = CreatNewNode(value);
	DLinkNode* cur = plist->head;
	//遍历链表,cur到最后尾指针位置
	while (cur != plist->tail) {

		cur = cur->_next;

	}
	cur->_next = InsertNode;
	InsertNode->_prev = cur;

	plist->tail = InsertNode;

	plist->size++;
	return InsertNode;
}

//打印整个链表
void PrintChar(DLinkList* plist, char* msg) {

	if (plist == NULL) {
		return;
	}
	printf("%s\n", msg);
	DLinkNode* cur1 = plist->head->_next;

	DLinkNode* cur2 = plist->tail;
	if (cur1 == NULL || cur2->_prev == plist->head) {
		//空链表
		printf("\n\n[head]<-[tail]\n\n");
		return;
	}
	//正着打印
	printf("\n\n\n[head]->");
	for (; cur1 != plist->tail; cur1 = cur1->_next) {

		printf("[%c]->", cur1->data);

	}
	printf("[%c]<-[tail]", cur1->data);
	//反着打印
	printf("\n\n\n[tail]->");
	for (; cur2 != plist->head; cur2 = cur2->_prev) {
		printf("[%c]->", cur2->data);
	}
	printf("[head]\n\n\n");
}

//尾删一个元素
void DLinkListPopBack(DLinkList* plist) {

	if (plist == NULL) {
		return;
	}
	DLinkNode* cur = plist->head;
	while (cur->_next != plist->tail) {

		cur = cur->_next;

	}
	DLinkNode* Delete = cur->_next;
	plist->tail = cur;

	Delete->_prev = NULL;
	cur->_next = NULL;
	
	plist->size--;

	DestoryNode(&Delete);
}

//头插一个元素
void DLinkListPushFront(DLinkList* plist, DLinkType value) {

	if (plist == NULL) {
		return;
	}
	DLinkNode* node = CreatNewNode(value);
	DLinkNode* cur = plist->head->_next;

	plist->head->_next = node;
	node->_prev = plist->head;

	node->_next = cur;
	cur->_prev = node;

	plist->size++;

}

//头删一个元素
void DLinkListPopFront(DLinkList* plist) {

	if (plist == NULL) {
		return;
	}
	//保存要删除的元素
	DLinkNode* Delete = plist->head->_next;
	DLinkNode* cur = plist->head->_next->_next;

	plist->head->_next = cur;
	cur->_prev = plist->head;

	plist->size--;
	DestoryNode(&Delete);
}

//查找某个元素
DLinkNode* DLinkListFind(DLinkList* plist, DLinkType to_find) {

	if (plist == NULL) {
		return;
	}
	DLinkNode* cur = plist->head;

	while (cur != plist->tail) {

		cur = cur->_next;
		if (cur->data == to_find) {
			//如果找到第一个值相等的元素,就返回cur
			return cur;
			
		}
	}
	//如果查找失败了,记得释放结点
	DLinkNode* error = CreatNewNode('-1');
	printf("链表里未保存此元素");
	return error;

}

//往指定位置之前插入一个元素
void DLinkListInsert(DLinkList* plist,DLinkNode* pos, DLinkType value) {

	if (pos == NULL) {
		return;
	}
	DLinkNode* cur = CreatNewNode(pos->data);
	DLinkNode* pos_next = pos->_next;
	//判断pos是否是最后一个元素
	if (pos_next == NULL) {

		pos->_next = cur;
		cur->_prev = pos;

		pos->data = value;

		plist->tail = cur;

		plist->size++;
	}
	else{
		pos->_next = cur;
		cur->_prev = pos;

		cur->_next = pos_next;
		pos_next->_prev = cur;

		pos->data = value;
		plist->size++;
	}
}

//往指定位置之后插入一个元素
void DLinkListInsertAfter(DLinkList* plist,DLinkNode* pos, DLinkType value) {

	if (plist == NULL) {
		return;
	}
	//创建新结点
	DLinkNode* insert = CreatNewNode(value);
	DLinkNode* pos_next = pos->_next;

	if (pos_next == NULL) {
		//当前结点是最后一个结点
		pos->_next  = insert;
		insert->_prev = pos;

		//更新尾指针和链表长度size
		plist->size++;
		plist->tail = insert;
	}
	else {
		//交换
		pos->_next = insert;
		insert->_prev = pos;

		insert->_next = pos_next;
		pos_next->_prev = insert;
		//更新链表长度size
		plist->size++;
	}
}

//删除指定位置的元素
void DLinkListErase(DLinkList* plist, DLinkNode* pos) {

	if (plist == NULL) {
		return;
	}
	DLinkNode* cur = plist->head;
	while (cur->_next != pos) {

		cur = cur->_next;
		if (cur->_next == NULL) {
			printf("pos位置传入错误");
			return;
		}

	}
	DLinkNode* Delete = pos;
	DLinkNode* pos_next = pos->_next;

	if (pos_next == NULL) {
		//pos为最后一个元素
		cur->_next = NULL;
		
		//更新链表size,释放删除的结点的空间
		plist->tail = cur;
		plist->size--;
		DestoryNode(&pos);

	}
	else{

		//开始拆除结点
		cur->_next = pos_next;
		pos_next->_prev = cur;

		plist->size--;
		DestoryNode(&pos);

	}
}

//删除指定值的元素
void DLinkListRemove(DLinkList* plist, DLinkType to_delete) {

	if (plist == NULL) {
		return;
	}
	DLinkNode* cur = plist->head;
	while (cur->_next->data != to_delete) {

		cur = cur->_next;
		if (cur->_next == NULL) {
			printf("链表中查不到此元素\n");
			return;
		}
	
	}
	DLinkNode* del_next = cur->_next->_next;
	DLinkNode* Delete = cur->_next;
	if (del_next == NULL) {
		//假如要删除的元素位于链表的最后一位,那么de_next一定为空指针
		cur->_next = NULL;

		//更新尾指针,size,并且释放删除的结点
		plist->tail = cur;
		plist->size--;
		DestoryNode(&Delete);
	}
	else {

		//拆除结点
		cur->_next = del_next;
		del_next->_prev = cur;

		plist->size--;
		DestoryNode(&Delete);
	}
}

//删除所有指定值的元素
void DLinkListRemoveAll(DLinkList* plist, DLinkType to_delete) {

	if (plist == NULL) {
		return;
	}
	int sz = plist->size;
	while (sz--) {

		//删除所有指定值的元素
		DLinkListRemove(plist, to_delete);

	}

}

//删除一个链表的所有元素
void DLinkListClear(DLinkList* plist) {

	if (plist == NULL) {
		return;
	}
	DLinkNode* cur = plist->head->_next;
	DLinkNode* to_free = plist->head->_next;

	plist->tail = plist->head;
	while (cur->_next != NULL) {

		cur = cur->_next;
		DestoryNode(&to_free);
		to_free = cur;

	}
	DestoryNode(&to_free);
	plist->head->_next = NULL;

}


test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"DLinkList.h"

#define TESTHEAD printf("//---------------%s-----------------\n",__FUNCTION__);

void TestPushBack() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");
}

void TestPopBack() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");

	DLinkListPopBack(plist);
	DLinkListPopBack(plist);
	DLinkListPopBack(plist);

	PrintChar(plist, "尾删三个元素");
}

void TestPushFront() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");

	DLinkListPushFront(plist, 'c');
	DLinkListPushFront(plist, 'b');
	DLinkListPushFront(plist, 'a');

	PrintChar(plist,"头插三个元素");
}

void TestPopFront() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");

	DLinkListPopFront(plist);
	DLinkListPopFront(plist);

	PrintChar(plist, "头删两个元素");
}

void TestFind() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkNode* pos_a = DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkNode* pos_f = DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");

	DLinkNode* cur1 = DLinkListFind(plist, 'a');
	if (pos_a->data == cur1->data) {
		printf("success!\n");
	}

}
void TestInsert() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkNode* pos_a = DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkNode* pos_f = DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");

	DLinkListInsert(plist,pos_a, 'u');
	PrintChar(plist, "在元素a之前插入元素u");

	DLinkListInsert(plist,pos_f, 'v');
	PrintChar(plist, "在元素f之前插入一个元素v");

}

void TestInsertAfter() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkNode* pos_a = DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkNode* pos_f = DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");

	DLinkListInsertAfter(plist,pos_a, 'u');
	PrintChar(plist, "在元素a之后插入元素u");

	DLinkListInsertAfter(plist,pos_f, 'v');
	PrintChar(plist, "在元素f之后插入元素v");
}

void TestErase() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkNode* pos_a = DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkNode* pos_f = DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");

	DLinkListErase(plist, pos_a);
	PrintChar(plist, "删除元素a");

	DLinkListErase(plist, pos_f);
	PrintChar(plist, "删除元素f");

}

void TestRemove() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");

	DLinkListRemove(plist, 'u');

	DLinkListRemove(plist, 'a');
	PrintChar(plist, "删除元素a");
	DLinkListRemove(plist, 'f');
	PrintChar(plist, "删除元素f");
	DLinkListRemove(plist, 'd');
	PrintChar(plist, "删除元素d");
}

void TestRemoveAll() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	PrintChar(plist, "尾插六个元素");

	DLinkListRemoveAll(plist, 'a');
	PrintChar(plist, "删除所有元素a");

}

void TestEmpty() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'a');
	PrintChar(plist, "尾插六个元素");

	int n = DLinkListEmpty(plist);
	printf("expect 0, actual: %d\n", n);

	DLinkListRemoveAll(plist, 'a');
	n = DLinkListEmpty(plist);
	printf("expect 1, actual:%d\n", n);
}

void TestClear() {
	DLinkList* plist = InitDLinkList();
	TESTHEAD;
	DLinkListPushBack(plist, 'a');
	DLinkListPushBack(plist, 'b');
	DLinkListPushBack(plist, 'c');
	DLinkListPushBack(plist, 'd');
	DLinkListPushBack(plist, 'e');
	DLinkListPushBack(plist, 'f');
	PrintChar(plist, "尾插六个元素");

	DLinkListClear(plist);
	PrintChar(plist, "删除链表里的所有元素");
}

int main() {
	TestPushBack();
	TestPopBack();
	TestPushFront();
	TestPopFront();
	TestFind();
	TestInsert();
	TestInsertAfter();
	TestErase();
	TestRemove();
	TestRemoveAll();
	TestEmpty();
	TestClear();
	system("pause");
	return 0;
}

应该还有不少bug,代码能力还有待加强,欢迎讨论
循环链表:从核心原理到C/C++实战实现与避坑指南 链表是数据结构中的基础线性结构,它通过节点和指针实现了数据的动态存储。其核心原理在于每个节点包含数据域和指向下一个节点的指针,从而形成链式访问。这种结构在需要频繁插入和删除操作的场景中,相比数组具有显著优势。循环链表作为链表的一种重要变体,通过将尾节点指向头节点形成闭环,将“循环”特性内化到数据结构本身,极大地简化了需要周期性处理数据的逻辑。这一技术价值使其在轮询调度、约瑟夫环问题、音乐播放列表和操作系统资源管理等应用场景中成为理想选择。本文聚焦于循环链表的边界条件处理与内存管理,深入探讨了在C++和C语言 阅读详情

相关推荐

GWAS与eQTL相结合,进一步筛选疾病相关基因

欢迎关注”生信修炼手册”!在GWAS分析结果中,大部分显著的SNP位点都位于非编码区,很难直接挖掘这些位点的调控机制。通常假设与疾病关联的SNP位点通过调控基因表达来发挥作用,而eQTL...

庐州月光的博客 1万+

数据结构-双链表和双循环链表(C语言代码)

双链表和双循环链表单链表双循环链表 单链表 单向链表特点:   1.可以轻松的到达下一个节点, 但是回到前一个节点是很难的.   2.只能从头遍历到尾或者从尾遍历到头(一般从头到尾) 双向链表特点   1.每次在插入或删除某个节点时, 需要处理四个节点的引用, 而不是两个. 实现起来要困难一些   2.相对于单向链表, 必然占用内存空间更大一些.   3.既可以从头遍历到尾, 又可以从尾遍历到头 双向链表的定义:   双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接

weixin_50246370的博客 514

网闸的基本配置

本文详细介绍了网闸的基本配置流程,包括物理连接与初始化、网络基础配置、核心数据交换策略配置、安全增强配置、管理与运维以及测试验证等关键步骤。网闸通过在物理隔离环境下建立"数据摆渡通道",实现特定业务数据的安全交换。配置时应遵循最小化、单向化、内容控制和审计原则,确保只开放必要通道,优先采用单向传输,进行内容安全检查并记录操作日志。不同厂商网闸的配置界面可能不同,但核心逻辑是相通的。

qq_39980997的博客 1839

C语言双向链表实现

C语言双向链表实现 链表是计算机编程中常用的一种数据结构,在大部分面向对象的编程语言中都会有封装好的类供用户直接使用,只有在数据结构课程中,老师才会要求学生用代码实现一个链表,而如果用C语言实现链表,除了要了解链表的特性之外,对于指针的操作也是一个重头戏。 开发环境:VS2013 开发系统:window7 头文件(TwoWayList.h)代码如下: #ifndef TWOWAY_...

lichangshun3的博客 1888

【Collibra 驱动 IPD 数据血缘治理】:三层图谱分层展示体系与全链路追踪的技术业务实践

(应用级/数据级/字段级)是理解复杂数据流动的核心手段。其价值不仅体现在可视化的直观性,更在于通过。技术保障血缘不可篡改性,进一步提升IPD数据治理的可靠性。,解决了跨层级血缘分析的性能与可用性矛盾。数据血缘图谱要素定义(字节跳动/腾讯云/信安标委)实现对IPD数据的精准追踪,而数据血缘图谱的。分层交互设计标准(智慧城市数据中台规范)Collibra技术文档(2024)字段级血缘的挑战与解决路径。自动优化血缘路径,并深化。字段级血缘技术实现方案。Collibra通过。图数据库性能优化原理。

百态·数智思维 | 聚焦大数据、量化与未来AI 1242

Python 驱动 CAD 二次开发:从零搭建自动化绘图环境

本文详细介绍了如何利用Python进行CAD二次开发,实现自动化绘图。通过win32com库建立Python与CAD软件的通信,文章从环境搭建、连接CAD、操作文档到核心绘图与批量处理,提供了完整的实战指南。该方法能显著提升机械设计、建筑绘图等领域的重复性工作效率,将创造力从繁琐劳动中解放出来。

weixin_29093169的博客 1226

C语言数据结构——双向循环链表

双向循环链表,就是在单链表的基础上加了一个前驱指针,链表首尾相连。 编译器:vc6 #include<stdio.h> #include<stdlib.h> //定义双向链表结构体 typedef struct student{ int score; struct student *next,*prio; } LinkList; //定义一个创建双向链表的方法 /* 传入链表长度 返回链表指针 */ LinkList *CreatLinkList(int n){

weixin_44230855的博客 425

中科蓝讯AB536X/AB892X芯片开发避坑指南:Downloader配置中那些容易忽略的细节

本文详细解析中科蓝讯AB536X/AB892X芯片开发中Downloader配置的关键细节,包括软开关机实现、触摸灵敏度调试、量产校频等常见问题。特别针对无PR口芯片的替代方案、触摸参数优化、校频流程等易忽略环节提供实用解决方案,帮助开发者规避量产风险,提升开发效率。

weixin_30687051的博客 475

C语言数据结构之双向链表

#include #include typedef struct DoubleList {     struct DoubleList *Pre;     struct DoubleList *Next;     int data; } Node; int Nodenum=0; //增加一个节点 int IsEmpty(Node **Start,Node **End) {

CrazyDevil 2284

2、通过mos管构成的逻辑门电路

一、总结 mos管 是构成 逻辑门电路 的最基本单元。 各个逻辑门电路的真值表如下: 二、各种门 1、非门 NOT 2、与门 AND 3、与非门 把上面与门电路 右边的 非门电路 去掉 NAND 4、或门 OR 5、或非门 NOR 把或门右边的非门电路去掉 6、异或门 XOR 两个输入相异为1,相同为0。 7、同或门 XNOR 两个输入相同为1,相异为0。 ...

engineer0的博客 4万+

GSEA富集分析实战:从数据准备到结果解读的完整R代码指南

本文提供了一份完整的GSEA富集分析实战指南,涵盖从R环境准备、数据质量控制到基因ID转换、参数优化和结果解读的全流程。通过详细的R代码示例和实用技巧,帮助研究人员高效完成基因集富集分析,特别针对生物信息学中常见的GSEA分析痛点提供了专业解决方案。

weixin_29246195的博客 536

数据结构之双链表(c语言附完整代码)

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。声明双链表typedef struct DNode //定义双链表结点类型 {//数据域 struct DNode * prior;//指向前驱结点 struct DNode * next;//指向后继结点 } DLinkNode;注意:本文章讨论的双链表是带头结点的双链表。

m0_62795460的博客 2709

文石NoteX3国行版安装 Google Play经验分享

文石NoteX3国行版安装 Google Play经验分享。

2301_80693261的博客 7592

数据结构——单向带头非循环链表的C语言代码实现

系列文章目录 数据结构——顺序表的C语言代码实现 数据结构——单向不带头非循环链表的C语言代码实现 数据结构——双向带头循环链表的C语言代码实现 文章目录系列文章目录前言一、List.h二、List.c三、test.c总结 前言 该篇文章是剩余六个链表之一的c语言代码实现,因为前两篇(单向不带头非循环与双向带头循环)中已经介绍过了链表中常见的接口函数和基础知识,故该篇文章只放代码,难点请看注释 一、List.h 代码如下: #define _CRT_SECURE_NO_WARNINGS 1 #inc

AZ10000000的博客 1155

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

链表之带头双向循环链表(C语言版)

我们之前已经介绍过链表的知识了,这里我们直接开始实现带头双向循环链表。

2301_79813267的博客 607

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

数据结构——单链表、双链表c语言实现

数据结构——单链表、双链表c语言实现 链表 特点(缺点):(1)非连续结构,实现结构复杂(2)不支持随机访问 使用场景:频繁插入删除 链表类型:单向、双向;带头、不带头;循环、非循环 三种属性可组成8中类型的结构 带尾指针的非循环链表:尾插时间复杂度O(1),尾删时间复杂度O(n)(遍历整个链表,将尾指针指向的前一个节点的next置为NULL) 双向循环链表:任意位置插入删除的...

qq_33431840的博客 771

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

链表详解(一)—— 无头单向非循环链表

文章目录链表介绍初始化链表打印单链表增加数据单链表的头插单链表的尾插删除数据单链表的头删单链表的尾删 链表介绍 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 实际中,链表的结构多种多样: 1、带头,不带头。 2、单向,双向。 3、循环,非循环。 通过以上的这些情况组合起来,就有八种

2021dragon的博客 3540

c++实现不带头结点的双向非循环链表(代码即注释,超详细版)

c++实现不带头结点的双向非循环链表(代码即注释,超详细版) 直接上代码 #include <iostream> using namespace std; class Node { public: int _data; Node *_pre; Node *_next; Node(int data = 0) : _data(data), _pre(nullptr), _next(nullptr) { // cout << "N

weixin_48617416的博客 1172

数据结构C(4)——循环链表、双向链表、双向链表的插入、删除

一、循环链表 循环链表是一种头尾相接的链表(即:表中最后一个结点的指针域指向头结点,整个链表形成一个环) 优点:从表中任一结点出发均可找到表中其他结点 注意:由于循环链表中没有NULL指针,故涉及遍历操作时,其终止条件就不再像非循环链表那样判断p或p->next是否为空,而是判断他们是否等于头指针 循环条件 p!=NULL → p!=L p->next!=NULL → p-&

Allure_07的博客 770

【数据结构入门】带头双向循环链表(List)详解(初始化、增、删、查、改)...

1、链表的种类:总共有8种,以带不带头,单向或者双向,循环或者不循环来组合形成。单向或者双向带头或者不带头循环或者非循环主要学习下面两种链表的功能实现无头单向非循环链表:又叫单链表,结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。<详...

weixin_64289779的博客 182

【数据结构实战】双向链表尾插法

双向链表尾插法的核心步骤包括:为新节点分配内存、找到尾节点(L->prev)、建立新节点与原尾节点的双向链接,最后完成与头节点的循环连接。本文提供了完整的C语言实现代码,包括初始化、尾插法、遍历和获取尾节点等操作,并通过主函数测试验证了功能。与单链表相比,双向链表在尾节点操作上更高效,无需遍历即可直接访问尾节点。

2301_82008805的博客 283

【数据结构】链表的增删查改

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表 中的指针链接次序实现的。注意:1.链式结构在逻辑上是连续的,但在物理上不一定连续2.现实中的结点一般都是从堆上申请出来的3.从堆上申请的空间,是按照一定的策略来分配,两次申请的空间,可能连续,也可能不连续。

烧鸡配油茶的博客 963

循环链表的介绍及创建(C语言代码实现)

如同单链表的创建,我们需要先创建一个头结点并且给其开辟内存空间,但与单链表不同的是,我们需要在开辟内存空间成功之后将头结点的next指向head自身,我们可以创建一个init函数来完成这件事情,为了以后的重复创建和插入,我们可以考虑在init重创建的结点next指向空,而在主函数调用创建之后手动讲head头结点的next指针指向自身。next表示指针,它永远指向自身的下一个结点,对于只有一个结点的存在,这个next指针则永远指向自身,对于一个链表的尾部结点,next永远指向开头。在主函数重调用可以是这样。

分享编程知识与技巧 致力于技术交流与学习 找我合作私聊 有偿解决计算机问题 612

我的数据结构3——链表(link list)

链表是一种线性动态数据结构,由若干个「节点(Node)」串联而成。与数组的「连续内存存储」本质不同,链表的节点在内存中可以分散存放,节点之间通过指针(引用)建立连接,从而形成一条 “数据链”。不需要预先分配固定内存,插入 / 删除元素时无需移动大量数据;但失去了随机访问能力,无法通过下标直接定位元素。循环条件写为,当Head指向最后一个节点时,Head->next为NULL,循环直接终止,最后一个节点永远不会被判断,漏查尾节点。修正:循环条件应为,逐个判断每个节点。

ChaoZiLL的博客 264

【C 数据结构】循环链表

在init重创建的结点next指向空,而在主函数调用创建之后手动 将head头结点的next指针指向自身。找到需要删除的结点,将其前一个结点的next指针直接指向删除结点的下一个结点。问题就是获取到链表的节点数同时也需要完成一次遍历才可以达成目标。在原有的双向链表的基础上,将尾部结点和头部结点进行互相连接。循环链表的尾指针指向的是链表的开头。

普罗米修斯的博客 1000
上一篇: 【数据结构】C语言实现双向链表(双向循环链表,无尾指针)
下一篇: 【数据结构】C语言实现顺序栈和链式栈
Qregi
博客等级 码龄9年 113粉丝 111原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值