链表(单向,双向,带头,不带头)

引言

线性表的另一种表示方法—— 链式存储结构,由于它不要求逻辑上相邻的数据元素在物理位置上也相邻,因此它没有顺序存储结构所具有的弱点,但同时也失去了顺序表可随机存取的优点。

带头单向链表

逻辑图示:

在这里插入图片描述
在这里插入图片描述

头文件设计singlelinklist.h

#ifndef  SINGLELINK_H
#define  SINGLELINK_H
//带头结点的单向链表结构设计
//设计结点类型
typedef int ElemType;
typedef struct ListNode {
	ElemType val;
	struct ListNode* next; //后继
}ListNode;

//链表
typedef struct LinkList {
	ListNode* head; //指向头结点
	int nodesize; //有效结点个数
}LinkList;
//1. 初始化
void InitList(LinkList* plist);
//2. 清空链表元素  将有效结点删除
void Clear(LinkList* plist);
//3. 销毁链表  清空链表+删除头结点
void Destory(LinkList* plist);
//4. 判空操作
bool IsEmpty(LinkList* plist);
//5. 头插数据
bool InsertHead(LinkList* plist, ElemType val);
//6. 尾插
bool InsertTail(LinkList* plist, ElemType val);
//7. 指定位置插入
bool InsertPos(LinkList* plist,int pos, ElemType val);
//8. 头删
bool DeleteHead(LinkList* plist);
//9. 尾删
bool DeleteTail(LinkList* plist);
//10. 按位置删除
bool DeletePos(LinkList* plist, int pos);
//10. 按位置删除  返回删除节点的元素值
ElemType DeletePos1(LinkList* plist, int pos);
//11. 删除val元素对应的结点
bool DeleteVal(LinkList* plist, ElemType val);
//12. 获取指定结点的前驱结点   12 23 34 45
ListNode*GetPrevNode(LinkList* plist, ElemType val);
//13. 获取指定结点的后驱结点
ListNode*GetNextNode(LinkList* plist, ElemType val);
//14. 删除指定结点的前驱结点 
bool DeletePrevNode(LinkList* plist, ElemType val);
//15. 删除指定结点的后驱结点
bool DeleteNextNode(LinkList* plist, ElemType val);
//16. 打印链表
void Show(LinkList* plist);
#endif // ! SINGLELINK_H
#pragma once

接口函数实现singlelinklist.cpp

在这里插入图片描述

在这里插入图片描述

#include "singlelinklist.h"
#include <stdlib.h>
#include <string.h>
#include <cassert>
#include <stdio.h>
//申请一个节点
ListNode* Buynode(ElemType val,ListNode*next) {
	ListNode* p = (ListNode*)malloc(sizeof(ListNode));
	if (p == NULL)  return nullptr;
	//memset(p,0,sizeof(ListNode));
	//可以初始化p指向的节点的val为空,p->next为空
	p->val = val;
	p->next = next;
	return p;
}


//1. 初始化
void InitList(LinkList* plist) {  //ListNode* head  size
	assert(plist != nullptr);
	plist->head = Buynode(0,nullptr); //带头结点
	plist->nodesize = 0;
}
//2. 清空链表元素  将有效结点删除
void Clear(LinkList* plist) {
	assert(plist!= nullptr);
	ListNode* p;
	while (plist->head->next != nullptr) {
		//对于空节点,有效节点为0,
		//plist->head!=nullptr,后面 plist->head->next为0,p->next 就会出错,空不能解引用
		p= plist->head->next;
		plist->head->next = p->next;//p->next=nullptr也可以
		free(p);
		plist->nodesize--;
	}
	
}
//如果是空链表的话,p就为空,p->next 就会出错,空不能解引用
//3. 销毁链表  清空链表+删除头结点
void Destory(LinkList* plist) {
	assert(plist != nullptr);
	Clear(plist);
	free(plist->head);
	plist->head = nullptr;//防止野指针
}

//4. 判空操作 TODO:
bool IsEmpty(LinkList* plist) {
	assert(plist != nullptr);
	return plist->head->next == nullptr;
	//return plist->nodesize==0;
}
//5. 头插数据 TODO:
bool InsertHead(LinkList* plist, ElemType val) {
	assert(plist != nullptr);
	ListNode* s = Buynode(val, 0);
	assert(s != nullptr);
	s->next = plist->head->next;//如果有效节点为0,p->next=nullptr
	plist->head->next = s;
	plist->nodesize++;
	return true;

}
//6. 尾插
bool InsertTail(LinkList* plist, ElemType val) {
	assert(plist != nullptr);
	ListNode* newnode = Buynode(val, nullptr);
	assert(newnode != nullptr);
	//找尾巴节点,该节点特点为.next=nullptr;
	ListNode* p = plist->head;
	while (p->next != nullptr) {
		p = p->next;
	}
	p->next = newnode;
	plist->nodesize++;
	return true;
}
//7. 指定位置插入 pos第个有效的节点的后一个位置;
bool InsertPos(LinkList* plist, int pos,ElemType  val) {
	assert(plist != nullptr && pos >= 1 && pos <= plist->nodesize+1);
	ListNode* newnode = Buynode(val, nullptr);
	assert(newnode != nullptr);
	ListNode* p = plist->head;
	for (int i = 0; i < pos-1; i++) {
		p = p->next;
	}
	newnode->next = p->next;
	p->next = newnode;
	plist->nodesize++;
	return true;
	
}
//8. 头删
bool DeleteHead(LinkList* plist) {
	assert(plist!=nullptr);
	if (IsEmpty(plist))return false;
	//指针指向待删除节点的地址
	ListNode* p = plist->head->next;
	//贯穿
	plist->head = p->next;//如果一个节点,p->next=nullptr;
	//释放p节点
	free(p);
	plist->nodesize--;
	return true;
}
//9. 尾删
bool DeleteTail(LinkList* plist) {
	assert(plist != nullptr);
	if (IsEmpty(plist))return false;
	ListNode* p = plist->head;
	while (p->next->next != nullptr) {
		p = p->next;
	}
	p->next = nullptr;
	free(p->next->next);
	plist->nodesize--;
	return true;
}
//10. 按位置删除
bool DeletePos(LinkList* plist, int pos) {
	assert(plist != nullptr&&pos>=1&&pos<=plist->nodesize);
	ListNode* p = plist->head;
	for (int i = 0; i < pos-1; i++) {
		p = p->next;
	}
	p->next = p->next->next;
	free(p->next);
	plist->nodesize--;
	return true;
}

//10. 按位置删除    返回删除节点的元素值
ElemType DeletePos1(LinkList* plist, int pos) {
	assert(plist != nullptr);
	if (IsEmpty(plist)) exit(EXIT_FAILURE);
	ListNode* p = plist->head;
	for (int i = 0; i < pos-1; i++) {
		p = p->next;	
	}
	ListNode* q = p->next;
	ElemType val = q->val;
	p->next = p->next->next;
	free(q);
	return val;

}
11. 删除val元素对应的结点   我自己的方法
//bool DeleteVal(LinkList* plist, ElemType val) {
//	assert(plist != nullptr && plist->nodesize > 0);
//	//1 2
//	// 
//	//2 3 5 5 6 5 7 8 9 6 3 
//	int pos = 1;
//	for (ListNode* p = plist->head->next; p != nullptr; p = p->next,pos++) {
//		if (p->val == val) {
//			DeletePos(plist, pos);
//			pos--;
//		}
//	}
//	return true;
//}

//11. 删除val元素对应的结点 1 2 3
bool DeleteVal(LinkList* plist, ElemType val) {
	//assert
	//找到该val所在结点的前驱结点,贯穿
	if (IsEmpty(plist))  return false;
	ListNode* q, * p = plist->head;
	while (p->next != nullptr) {
		if (p->next->val == val) {
			q = p->next; //q标记的是待删结点      删除当前q   
			p->next = p->next->next;
			free(q);
		}
		else {
			p = p->next;
		}
		
	}
	return true;
}
12. 获取指定结点的前驱结点   12 23 34 45
//ListNode GetPrevNode(LinkList* plist, ElemType val) {
//	assert(plist != nullptr);
//	ListNode* p = plist->head;
//	while (p->next->val != val) {//没有考虑空链表的情况
//		p = p->next;
//	}
//	return *p;
//}
// 
//12. 获取指定结点的前驱结点   12 23 34 45
ListNode*GetPrevNode(LinkList* plist, ElemType val) {
	//assert
	if (IsEmpty(plist)) return nullptr;
	ListNode* q = nullptr;
	for (ListNode* p = plist->head; p->next != nullptr; p = p->next) {
		if (p->next->val == val) {
			q = p;
			break;
		}
	}
	return q;
}
//13. 获取指定结点的后驱结点
//ListNode *GetNextNode(LinkList* plist, ElemType val) {
//	assert(plist != nullptr);
//	ListNode* p = plist->head;
//	while (p->next->val != val) {
//		p = p->next;//没有该点,就会崩掉
//	}
//	if (p->next->next == nullptr)return;//防止崩掉
//	return (p->next->next);
//}
ListNode* GetNextNode(LinkList* plist, ElemType val) {
	//assert
	ListNode* p = plist->head->next;
	for (; p != nullptr && p->val != val; p = p->next) {
		;
	}
	return p != nullptr ? p->next : nullptr;
}
//14. 删除指定结点的前驱结点 
bool DeletePrevNode(LinkList* plist, ElemType val) {
	//assert(plist != nullptr);
	//ListNode* p = plist->head;
	//int pos = 1;
	//while (p->next->val != val) {//可能会崩
	//	p = p->next;
	//	pos++;
	//}
	//if (pos <= 1)return false;
	//DeletePos(plist, pos-1);
	if (IsEmpty(plist)) return false;
	ListNode* q;
	for (ListNode* p = plist->head; p->next->next != nullptr; p = p->next) {
		if (p->next->next->val == val) { //p标记的是val所在结点的前前个
			q = p->next;
			p->next = p->next->next;// 删除val的前驱结点
			free(q);
			break;
		}
	}
	return true;

}
//15. 删除指定结点的后驱结点
bool DeleteNextNode(LinkList* plist, ElemType val) {
	assert(plist != nullptr);
	if (IsEmpty(plist))return false;
	ListNode* q;
	for (ListNode* p = plist->head; p->next->next != nullptr;p=p->next ) {
		if (p->next->val == val) {
			q = p->next->next;
			p->next->next = q->next;
			free(q);
			break;
		}
	}
	return true;
}
//16. 打印链表
void Show(LinkList* plist) {
	for (ListNode* p = plist->head->next; p != nullptr; p = p->next) {
		printf("%5d", p->val);
	}
	printf("\n");
}

部分函数实现图示

初始化一个带头单链表

在这里插入图片描述

在ptr指针之后插入数据元素

在这里插入图片描述

删除ptr所指向的后续结点(数据元素)

在这里插入图片描述

不带头单向链表

逻辑图示:

在这里插入图片描述

头文件设计noheadsinglelinklist.h

#ifndef  SINGLELINKNOHEAD_H
#define  SINGLELINKNOHEAD_H
//不带头结点的单向链表结构设计
//设计结点类型
typedef int ElemType;
typedef struct ListNode {
	ElemType val;
	struct ListNode* next; //后继
}ListNode;

//链表
typedef struct LinkList {
	ListNode* head; //指向头
	int nodesize; //有效结点个数
}LinkList;

//1. 初始化
void InitList(LinkList* plist);
//2. 清空链表元素  将有效结点删除
void Clear(LinkList* plist);
//3. 销毁链表  清空链表+删除头结点
void Destory(LinkList* plist);
//4. 判空操作
bool IsEmpty(LinkList* plist);
//5. 头插数据
bool InsertHead(LinkList* plist, ElemType val);
//6. 尾插
bool InsertTail(LinkList* plist, ElemType val);
//7. 指定位置插入
bool InsertPos(LinkList* plist, int pos, ElemType val);
//8. 头删
bool DeleteHead(LinkList* plist);
//9. 尾删
bool DeleteTail(LinkList* plist);
//10. 按位置删除
ElemType DeletePos(LinkList* plist, int pos);
//11. 删除val元素对应的结点
bool DeleteVal(LinkList* plist, ElemType val);
//12. 获取指定结点的前驱结点   12 23 34 45
ListNode* GetPrevNode(LinkList* plist, ElemType val);
//13. 获取指定结点的后驱结点
ListNode* GetNextNode(LinkList* plist, ElemType val);
//14. 删除指定结点的前驱结点 
bool DeletePrevNode(LinkList* plist, ElemType val);
//15. 删除指定结点的后驱结点
bool DeleteNextNode(LinkList* plist, ElemType val);
//16. 打印链表
void Show(LinkList* plist);
#endif // ! SINGLELINKNOHEAD_H

接口函数实现noheadsinglelinklist.cpp

#include"noheadsinglelinklist.h"
#include<assert.h>
#include<stdlib.h>
#include<stdio.h>
//不带头节点链表实现
ListNode* BuyNode(ElemType val, ListNode* next) {
	ListNode* node = (ListNode*)malloc(sizeof(ListNode));
	if (node == nullptr)return nullptr;
	node->next = next;
	node->val = val;
	return node;
}
//1. 初始化
void InitList(LinkList* plist) {
	assert(plist != nullptr);
	// 带头结点: plist->head = BuyNode(0, nullptr);
	//不带头
	plist->head = nullptr;
	plist->nodesize = 0; //当前有效结点个数0
}
//2. 清空链表元素  将有效结点删除
void Clear(LinkList* plist) {
	assert(plist != nullptr);
	ListNode* p;  //不带头结点,head 是指针 指向有效结点
	while (plist->head != nullptr) {
		DeleteHead(plist);
	}
}
//3. 销毁链表  清空链表+不存在头结点
void Destory(LinkList* plist) {
	assert(plist != nullptr);
	Clear(plist);
}
//4. 判空操作
bool IsEmpty(LinkList* plist) {
	assert(plist != nullptr);
	//带头结点写法:return plist->head->next == nullptr;
	//不带头结点写法
	return plist->head == nullptr;
}
//5. 头插数据
bool InsertHead(LinkList* plist, ElemType val) {
	assert(plist != nullptr);
	ListNode* p = BuyNode(val, 0);
	assert(p != nullptr);
	p->next = plist->head;
	plist->head = p;
	plist->nodesize++;
	return true;
}
//6. 尾插
bool InsertTail(LinkList* plist, ElemType val) {
	assert(plist != nullptr);
	ListNode* newnode = BuyNode(val, nullptr);
	assert(newnode != nullptr);
	if (IsEmpty(plist)) {
		plist->head = newnode;
	}
	else {
		ListNode* p = plist->head;
		while (p->next != nullptr) {
			p = p->next;
		}
		p->next = newnode;
	}
	plist->nodesize++;
	return true;
}
//7. 指定位置插入
bool InsertPos(LinkList* plist, int pos, ElemType val) {
	assert(plist != nullptr && pos >= 1 && pos <= plist->nodesize);
	ListNode* newnode = BuyNode(val, nullptr);
	assert(newnode != nullptr);
	if (pos == 1) {
		InsertHead(plist, val);  //跟带头结点区别
	}
	else {
		ListNode* p = plist->head; //head ->1 2 3 4       pos  1   
		for (int i = 1; i < pos - 1; i++) { //找该位置前一个结点
			p = p->next;
		}
		newnode->next = p->next;//先牵右
		p->next = newnode;//再牵左
		plist->nodesize++;
	}
	return true;
}
//8. 头删
bool DeleteHead(LinkList* plist) {
	assert(plist != nullptr);
	if (IsEmpty(plist))return false;
	ListNode* p = plist->head;
	plist->head = p->next;
	free(p);
	plist->nodesize--;
	return true;
}
//9. 尾删
bool DeleteTail(LinkList* plist) {
	assert(plist != nullptr);
	if (IsEmpty(plist))return false;

	if (plist->nodesize == 1) {

		free(plist->head);
		plist->head = nullptr;
	}
	else {
		ListNode* p = plist->head;
		while (p->next->next != nullptr) {
			p = p->next;
		}
		free(p->next);
		p->next = nullptr;
	}
	plist->nodesize--;
	return true;
}
///以下代码针对不带头结点如何修改
//10. 按位置删除  返回删除结点的元素值
ElemType DeletePos(LinkList* plist, int pos) {
	//assert   
	if (IsEmpty(plist)) exit(EXIT_FAILURE);
	ListNode* q, * p = plist->head;
	ElemType val;
	if (pos == 1) {
		q = p;
		val = q->val;
		p = p->next;
		free(q);
	}
	else {
		for (int i = 1; i < pos - 1; i++) { // p标记的是待删节点前一个
			p = p->next;
		}
		q = p->next; //q标记的是待删结点
		val = q->val;
		//删除当前q   
		p->next = p->next->next;
		free(q);
	}
	return val;
}
//11. 删除val元素对应的结点 1 2 2 3
bool DeleteVal(LinkList* plist, ElemType val) {
	//assert
	//找到该val所在结点的前驱结点,贯穿
	if (IsEmpty(plist))  return false;
	ListNode* q ;
	ListNode*p = plist->head;
	while (p->val==val)
	{
		q = p; //q标记的是待删结点      删除当前q   
		plist->head = p->next;
		free(q);
		p = plist->head;
	}
	while (p->next != nullptr) {
		if (p->next->val == val) {//使用未初始化的内存*p
			q = p->next; //q标记的是待删结点      删除当前q   
			p->next = p->next->next;
			free(q);
		}
		else {
			p = p->next;
		}
	}
	return true;
}
12. 获取指定结点的前驱结点   12 23 34 45
//ListNode GetPrevNode(LinkList* plist, ElemType val) {
//	assert(plist != nullptr);
//	ListNode* p = plist->head;
//	while (p->next->val != val) {//没有考虑空链表的情况
//		p = p->next;
//	}
//	return *p;
//}
// 
//12. 获取指定结点的前驱结点   12 23 34 45
ListNode* GetPrevNode(LinkList* plist, ElemType val) {
	//assert
	if (IsEmpty(plist)) return nullptr;
	ListNode* q = nullptr;
	for (ListNode* p = plist->head; p->next != nullptr; p = p->next) {
		if (p->next->val == val) {
			q = p;
			break;
		}
	}
	return q;
}
//13. 获取指定结点的后驱结点
//ListNode *GetNextNode(LinkList* plist, ElemType val) {
//	assert(plist != nullptr);
//	ListNode* p = plist->head;
//	while (p->next->val != val) {
//		p = p->next;//没有该点,就会崩掉
//	}
//	if (p->next->next == nullptr)return;//防止崩掉
//	return (p->next->next);
//}
ListNode* GetNextNode(LinkList* plist, ElemType val) {
	//assert
	ListNode* p = plist->head;
	for (; p != nullptr && p->val != val; p = p->next) {
		;
	}
	return p != nullptr ? p->next : nullptr;
}
//14. 删除指定结点的前驱结点 
bool DeletePrevNode(LinkList* plist, ElemType val) {
	//assert(plist != nullptr);
	//ListNode* p = plist->head;
	//int pos = 1;
	//while (p->next->val != val) {//可能会崩
	//	p = p->next;
	//	pos++;
	//}
	//if (pos <= 1)return false;
	//DeletePos(plist, pos-1);
	if (IsEmpty(plist)) return false;
	ListNode* q;
	ListNode* p = plist->head;
	if (p->next == nullptr)return false;
	if (p->next->val == val && p->next != nullptr) {
		DeleteHead(plist);
		return true;
	}
	for (; p->next->next != nullptr; p = p->next) {
		if (p->next->next->val == val) { //p标记的是val所在结点的前前个
			q = p->next;
			p->next = p->next->next;// 删除val的前驱结点
			free(q);
			break;
		}
	}
	return true;

}
//15. 删除指定结点的后驱结点
bool DeleteNextNode(LinkList* plist, ElemType val) {
	assert(plist != nullptr);
	if (IsEmpty(plist))return false;
	ListNode* q;
	for (ListNode* p = plist->head; p->next != nullptr; p = p->next) {
		if (p->val == val) {
			q = p->next;
			p->next = q->next;
			free(q);
			break;
		}
	}
	return true;
}
//16. 打印链表
void Show(LinkList* plist) {
	if (IsEmpty(plist))return;
	for (ListNode* p = plist->head; p != nullptr; p = p->next) {
		printf("%5d", p->val);
	}
	printf("\n");
}

带头双向循环链表

示意图

带头双向循环链表
在这里插入图片描述
插入一个新的节点
在这里插入图片描述
删除一个节点
在这里插入图片描述

头文件设计 结构体 设计

#include"DuLinkList.h"
#include<stdio.h>
#include<stdlib.h>
#include <cassert>
//带头双向循环链表
typedef int ElemType;
//有三个域,分别是数据域data 前面一个节点的地址,
//和后面一个节点的地址
typedef struct DuNode
{
	struct DuNode* prev;
	struct DuNode* next;
	ElemType data;
}DuNode, * PDuNode;
//定义一个结构体DuLinkList  里面一个指针,指向一个链表,
//一个cuisize标记当前的节点个数
typedef struct DuLinkList
{
	PDuNode head; // 
	int cursize;  // 
}DuLinkList;

函数接口实现

//购买一个节点,这个并且将这个点的next prev指向它自己
// 不带参数,就是用默认参数,就是空指针,
//该头结点的前驱和后继全都指向自身
DuNode* Buynode(DuNode* parg , DuNode* narg )//重定义默认参数1  2
{
	DuNode* s = (DuNode*)malloc(sizeof(DuNode));
	if (nullptr == s) exit(1); // .c NULL
	s->prev = parg == nullptr ? s : parg;
	s->next = narg == nullptr ? s : narg;

	return s;
}
void Freenode(DuNode* p) {
	free(p);
}
// 不带参数,就是用默认参数,该头结点的前驱和后继全都指向自身
//初始化DuLinkList        指向头结点
void InitList(DuLinkList* plist)
{
	assert(plist != nullptr);
	plist->cursize = 0;
	plist->head = Buynode();
	
}
//由于是循环链表,所以头结点的前一个节点就是尾巴
//当p不为头结点,就可以一直释放p节点,当尾巴节点为头节点时,就可以
//结束,该链表为空,只留下了头结点
void Clear(DuLinkList* plist) {
	assert(plist != nullptr);
	DuNode* p = plist->head->prev;
	while (p != plist->head) {
		Freenode(p);
		p = p->prev;
	}
	plist->cursize = 0;
}
//因为有头节点,所以销毁该链表,需要分两步,
// //第一步清空所有的数据节点,
//第二步,就是将头结点释放
void Destory(DuLinkList* plist) {
	assert(plist != nullptr);
	Clear(plist);
	Freenode(plist->head);
	plist->head = nullptr;

}
//在ptr指针所指向的节点的前面插入一个点
//注意顺序,ptr->prev= Buynode(ptr->prev, ptr);//连接了三根线
//ptr->prev 指向了一个新的节点,该新节点prev指向了ptr的前面的节点,next指向了ptr
//最后将s的prev的next指向s就连接完毕,最后记得cursize++
void Insert(DuLinkList* plist, DuNode* ptr, ElemType val)
{
	
	assert(plist != nullptr && ptr != nullptr);
	ptr->prev= Buynode(ptr->prev, ptr);//连接了三根线
	DuNode* s = ptr->prev;
	s->prev->next = s;
	s->data = val;
	plist->cursize++;	 
}
//利用Insert()进行头插和尾插
void Push_Front(DuLinkList* plist, ElemType val)
{
	assert(plist != nullptr);
	Insert(plist, plist->head->next, val);
}
void Push_Back(DuLinkList* plist, ElemType val)
{
	assert(plist != nullptr);
	Insert(plist, plist->head, val);
}
//删除节点贯穿的时候不用标记
void Earse(DuLinkList* plist, DuNode* ptr) {
	assert(plist != nullptr&&ptr!=nullptr);
	ptr->prev->next = ptr->next;
	ptr->next->prev = ptr->prev;
	Freenode(ptr);
	plist->cursize--;
}
void PopFront(DuLinkList* plist) {
	assert(plist != nullptr);
	Earse(plist, plist->head->next);
}
void PopBack(DuLinkList* plist) {
	assert(plist != nullptr);
	Earse(plist, plist->head->prev);
}
int GetSize(DuLinkList* plist) {
	assert(plist != nullptr);
	return plist->cursize;
}
//用p指针遍历,当p->val==val 返回p的值,不等于val,往后遍历,如果么有
//该值,遍历一遍退出,即,p==plist->head;
DuNode* FindValue(DuLinkList* plist, ElemType val) {
	assert(plist != nullptr);
	DuNode* p = plist->head->next;
	while (p!=plist->head&&p->data!=val)
	{
		p = p->next;
	}
	return p == plist->head ? nullptr : p;
}
bool IsEmpty(DuLinkList* plist) {
	assert(plist != nullptr);
	return plist->cursize == 0;
}
void Insertorder(DuLinkList*plist,ElemType val) {
	assert(plist != nullptr);
	DuNode* p = plist->head->next;
	while (val>p->data)
	{
		p = p->next;
	}
	Insert(plist, p, val);
}
void Print(DuLinkList* plist) {
	assert(plist != nullptr);
	DuNode* p = plist->head->next;
	while (p != plist->head) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值