数据结构之链表操作(单链表,单向循环链表,双向循环链表)查找节点,插入节点,删除节点,更新节点,新建节点,遍历,清空,判断空链表等操作

链表和数组的优缺点

数组:
优点,支持随机访问,内存消耗较小
缺点,大小固定,插入和删除操作效率低
链表:
优点,动态比较灵活开辟空间,插入和删除操作效率高
缺点,不支持随机访问,内存消耗较大,需要额外的指针

一、线性表

线性表结构的数据是依次排列(一对一)

(1)顺序结构:数组,顺序栈,顺序队列(顺序表)

(2)链式存储:链表,链式栈,链式队列(线性表)

二、链表
2.1、链表

​ 链表是一种具体的数据结构

​ 1、逻辑上:一对一的排列

​ 2、存储上:非连续的

​ 3、相关操作:查找节点,插入节点,删除节点,更新节点,新建节点,遍历,清空,判断空链表等

​ 4、链表分类

​ 单向链表,双向链表,单向循环链表,双向循环链表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CZZ9uKEz-1652703194449)(file:///C:/Users/yyh/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]

​ 5、链式存储特点

​ 不需要一块连续内存

​ 插入和删除效率极高

2.2、单向链表

链式存储结构:数据元素是随机存储的,通过指针表示数据之间的逻辑关系

(1)单向链表的节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YSlVm5li-1652703194450)(file:///C:/Users/yyh/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg)]

单向链表节点模板声明

typedef [节点数据域类型] Datatype;

//单向链表节点
struct Node
{
	Datatype data;		//数据域
	struct Node *next;	    //指针域	
};

经常给节点结构体和节点结构体指针取别名,方便以后的使用

//单向链表节点
typedef struct Node
{
	Datatype data;		//数据域
	struct Node *next;	//指针域	
}ListNode;

单链表初始化

一般定义一个不带数据的节点(头结点),用来表示整个链表的头部

//初始化链表(新建一个不带数据的头结点)
ListNode * InitNode()	//不带数据的头节点
{
	ListNode * head=(ListNode *)malloc(sizeof(ListNode));
	if(head != NULL){
		head->next = NULL;
	}else{
		return NULL;
	}
	return head;
}

//调用空链表初始化
	ListNode *head = init();
	if (head == NULL)
	{
		return -1;
	}

(2)查找节点,插入节点,删除节点,更新节点,新建节点,遍历,清空,判断空链表

新建节点

//新建节点
ListNode * CreateNode(Datatype data)
{
	ListNode * new=(ListNode *)malloc(sizeof(ListNode));
	if (new!=NULL){
		new->next = NULL;
	}else{
		return NULL;
	}
	new->data = data;
	return new;
}

插入节点

尾插法

//插入节点,尾插法
void InsertNodeTail(ListNode *head,ListNode * new)
{
	ListNode *p=head;//定义一个临时中间变量p,用来遍历链表,找到最后的节点,防止头结点地址发生改变
	while(p->next != NULL)
	{
		//一个一个往后找
		p = p->next;
	}
	//找到最后一个节点之后,将最后一个节点的next设置为new(新节点的地址)
	p->next = new;
}

头插法

//头插法
void InsertNodeHead(ListNode *head,ListNode *new)
{
	new->next = head->next;
	head->next=new;
}

遍历链表

//遍历链表
void Display(ListNode *head)
{
  ListNode *p=head->next;
  while(p!=NULL)
  {
  	printf("%d  ",p->data);
  	p=p->next;
  }
  printf("\n");
}

查找节点

//查找节点
ListNode *FindNode(ListNode *head,Datatype data)
{
	ListNode *p=head->next;
	while(p!=NULL)
	{
		if(p->data == data)
		{
			return p;
		}
		p=p->next;
	}
	return NULL;
}

删除节点

//删除节点,以数据来删除
Node_p dele_node(Node_p head, Datatype dele_data)
{
	Node_p p = head;
	while(p->next != NULL)
	{	
		if (p->next->data == dele_data)
		{
			Node_p dele = p->next;
			p->next = dele->next;//防止链表的链式关系断开
			free(dele);
			dele = NULL;
			return p;
		}
		p = p->next;
	}
	return NULL;
}
//删除节点,以节点来删除
ListNode * DeleteNode(ListNode *head,ListNode *delNode)
{
	ListNode *p=head;
	while(p->next!=NULL)
	{
		if(p->next == delNode)
		{
			ListNode *tmp = p->next;
			p->next = tmp->next;
			free(tmp);
			tmp=NULL;
			return p->next;
		}
		p=p->next;
	}
	return NULL;
}

//删除所有数据为dele_data的节点
ListNode *DeleteNodeByDate(ListNode *head,Datatype data)
{
	ListNode *p=head;
	while(p->next!=NULL)
	{
		if(p->next->data == data)
		{
			ListNode *tmp=p->next;
			p->next=p->next->next;//防止链表的链式关系断开
			free(tmp);
			tmp=NULL;
			continue;
		}
		p=p->next;
	}
	return NULL;
}

更改节点

//更改节点
void UpdateNode(ListNode *head,DateType old_data,Datatype new_data)
{
	ListNode *p = FindNode(head, old_data);
	if (p != NULL)
	{
		p->data = new_data;
	}
	else
	{
		printf("没有找到要修改的节点\n");
	}
}

判断空链表

//判断空链表
bool IsEmpty(ListNode * head)
{
   return (head->next == NULL);
}

清空链表

//清空链表
void ClearLinkNode(ListNode* head)
{
	if(head == NULL || IsEmpty(head))
	{
		return ;
	}
	while(head->next != NULL)
	{
		ListNode* dele = head->next;
		head->next = dele->next;
		free(dele);		
		dele->next = NULL;
		dele = NULL;
	}
}

取出节点

//取出节点,节点不删除
ListNode* GetNode(ListNode* head, Datatype data)
{
   if(head == NULL || is_empty(head))
   {
   	return NULL;
   }
   ListNode* p = head;
   while(p->next != NULL)
   {
   	if (p->next->data == data)
   	{
   		ListNode* node = p->next;
   		p->next = node->next;
   		return node;
   	}
   	p = p->next;
   }
   return NULL;
}

指定位置插入节点

void InsertNode_node(ListNode* node1,ListNode* node2)
{
    //将node1插入到node2后面
  if (node1 == NULL || node2 == NULL)
	{
		return;
	}
	//相当于头插法,node2为头结点,node1为新节点
	//node1->next = node2->next;
	//node2->next = node1;
  InsertNodeHead(node2, node1);
}

移动节点

//移动节点
void move_node(ListNode* head, Datatype data1, Datatype data2)
{
	//取出移动的节点data1
	ListNode* node1 = GetNode(head, data1);
	//找到data2的节点
	ListNode* node2 = FindNode(head, data2);
	//将data1插入到data2后面
	if (node1 == NULL || node2 == NULL)
	{
		return;
	}
	node1->next = node2->next;
	node2->next = node1;
}

(3)单向链表 完整代码
#include <stdio.h>
#include <stdlib.h>

typedef int Datatype;
typedef struct Node
{	
	Datatype data;
	struct Node *next;	
}ListNode;


ListNode * InitNode()	//不带数据的头节点
{
	ListNode * head=(ListNode *)malloc(sizeof(ListNode));
	if(head != NULL){
		head->next = NULL;
	}else{
		return NULL;
	}
	return head;
}

//创建
ListNode * CreateNode(Datatype data)
{
	ListNode * new=(ListNode *)malloc(sizeof(ListNode));
	if (new!=NULL){
		new->next = NULL;
	}else{
		return NULL;
	}
	new->data = data;
	return new;
}
//尾插
void InsertNodeTail(ListNode *head,ListNode * new)
{
	ListNode *p=head;
	while(p->next!=NULL)
	{
		p=p->next;
	}
	p->next = new;
}
//头插
void InsertNodeHead(ListNode *head,ListNode *new)
{
	new->next = head->next;
	head->next=new;
}

void Display(ListNode *head)
{
	ListNode *p=head->next;
	while(p!=NULL)
	{
		printf("%d  ",p->data);
		p=p->next;
	}
	printf("\n");
}

ListNode * DeleteNode(ListNode *head,ListNode *delNode)
{
	ListNode *p=head;
	while(p->next!=NULL)
	{
		if(p->next == delNode)
		{
			ListNode *tmp = p->next;
			p->next = tmp->next;
			free(tmp);
			tmp=NULL;
			return p->next;
		}
		p=p->next;
	}
	return NULL;
}

//删除
ListNode *DeleteNodeByDate(ListNode *head,Datatype data)
{
	ListNode *p=head;
	while(p->next!=NULL)
	{
		if(p->next->data == data)
		{
			ListNode *tmp=p->next;
			p->next=p->next->next;
			free(tmp);
			tmp=NULL;
			continue;
		}
		p=p->next;
	}
	return NULL;
}

//查找
ListNode *FindNode(ListNode *head,Datatype data)
{
	ListNode *p=head->next;
	while(p!=NULL)
	{
		if(p->data == data)
		{
			return p;
		}
		p=p->next;
	}
	return NULL;
}

//更改数据
ListNode *UpdateNode(ListNode *head,DateType old_data,Datatype new_data)
{
	ListNode *p=head->next;
	while(p!=NULL)
	{
		if(p->data == old_data)
		{
			p->data = new_data;
			// return p;
		}
		p=p->next;
	}
	return NULL;
}

//删除所有数据为data的节点
ListNode *DeleteNodeAllSame(ListNode *head,Datatype data)
{
	ListNode *p=head;
	while(p->next!=NULL)
	{
		if (p->next->data == data)
		{
			ListNode *tmp=p->next;
			p->next=tmp->next;
			free(tmp);
			tmp=NULL;
			continue;
		}
		p=p->next;
	}
	return NULL;
}


//判断空链表
bool IsEmpty(ListNode * head)
{
	return (head->next == NULL);
}

//清空链表
void ClearLinkNode(ListNode* head)
{
	if(head == NULL || IsEmpty(head))
	{
		return ;
	}
	while(head->next != NULL)
	{
		ListNode* dele = head->next;
		head->next = dele->next;
		free(dele);		
		dele->next = NULL;
		dele = NULL;
	}
}

//取出节点
ListNode* GetNode(ListNode* head, Datatype data)
{
	if(head == NULL || is_empty(head))
	{
		return NULL;
	}
	ListNode* p = head;
	while(p->next != NULL)
	{
		if (p->next->data == data)
		{
			ListNode* node = p->next;
			p->next = node->next;
			return node;
		}
		p = p->next;
	}
	return NULL;
}

//移动节点
void move_node(ListNode* head, Datatype data1, Datatype data2)
{
	//取出移动的节点data1
	ListNode* node1 = GetNode(head, data1);
	//找到data2的节点
	ListNode* node2 = FindNode(head, data2);
	//将data1插入到data2后面
	if (node1 == NULL || node2 == NULL)
	{
		return;
	}
	node1->next = node2->next;
	node2->next = node1;
}

void InsertNode_node(ListNode* node1,ListNode* node2)
{
	  //将node1插入到node2后面
	if (node1 == NULL || node2 == NULL)
  	{
  		return;
  	}
  	//相当于头插法,node2为头结点,node1为新节点
  	//node1->next = node2->next;
  	//node2->next = node1;
    InsertNodeHead(node2, node1);
}


int main(int argc, char const *argv[])
{
	int i,n=10;
	ListNode * head = InitNode();
	
	for(i=0;i<n;i++)
	{
		ListNode *new=NULL;
		if(i<=3||i>5)
				new = CreateNode(i);
		else
			new = CreateNode(4);
		// InsertNodeTail(head,new);	//尾插
		InsertNodeHead(head,new);		//头插
	}
	Display(head);

	int old_num,new_num,num;
	printf("search num :\n");
	scanf("%d",&num);
	ListNode *tmp = FindNode(head,num);
	if(tmp!=NULL)
	{
		printf("找到 %d\n",tmp->data);
	}
	else
	{
		printf("未找到!\n");
	}
	printf("delete num : ");
	scanf("%d",&num);
	if(DeleteNodeByDate(head,num));
	{
		printf("delete successfully\n");
	}
	DeleteNodeAllSame(head,num);
	Display(head);

	printf("update old_num : ");
	scanf("%d",&old_num);
	printf("update new_num : ");
	scanf("%d",&new_num);
	UpdateNode(head,old_num,new_num);
	Display(head);

	return 0;
}

list.h

#ifndef LIST_H_
#define LIST_H_

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


//链表必须为单向链表,链表结点必须包含next指针域
/*list 为链表头指针*/
#define List_Init(list, list_node_t) {					\
		list=(list_node_t*)malloc(sizeof(list_node_t)); \
		(list)->next=NULL;					\
	}

//list 为链表头指针,tmpPtr为链表结点临时指针变量
#define List_Free(list, list_node_t) {			\
		assert(NULL!=list);						\
		list_node_t *tmpPtr;					\
		while(NULL!=(tmpPtr=(list)->next)){ 	\
			(list)->next=tmpPtr->next;			\
			free(tmpPtr);						\
		}										\
	}

//list 为链表头指针,tmpPtr为链表结点临时指针变量
#define List_Destroy(list, list_node_t) {		\
		assert(NULL!=list);						\
		List_Free(list, list_node_t)			\
		free(list);								\
		(list)=NULL;							\
	}



//遍历链表
#define List_ForEach(list, curPos) 		\
	 for (   curPos = (list)->next;  	\
		  	  	  curPos != NULL;       \
		  	  	  curPos=curPos->next	\
	    )
	    
	    
	    
//链表头插法,list为头指针,new为新节点
#define List_AddHead(list, newNode) {			\
		(newNode)->next=(list)->next;		 	\
		(list)->next=newNode;				 	\
	}



//链表尾插法,list为头指针,curPos为循环变量 new为新节点
#define List_AddTail(list, curPos ,newNode) {			\
		for(curPos = (list); ;curPos=curPos->next){		\
			if((curPos)->next == NULL){					\
				(curPos)->next = (newNode);				\
				break;									\
			}											\
		}												\
	}

//将新节点newNode加入到node之前
#define List_InsertBefore(node, newNode) {		\
		(newNode)->prev=(node)->prev; 		 	\
		(node)->prev->next=newNode;			 	\
		(node)->prev=newNode;			 		\
		(newNode)->next=node;			 		\
	}

//将新节点newNode加入到node之后
#define List_InsertAfter(node, newNode) {		\
		(newNode)->next=node->next;			 	\
		(node)->next=newNode;				 	\
	}

//判断链表是否为空,list为头指针
#define List_IsEmpty(list)  (((list) != NULL)


//删除并释放链表结点node,
#define List_FreeNode(head ,node,list_node_t) {             		\
			assert(NULL!=node);								\
			if(node -> next != NULL){				        \
				list_node_t *temp = node->next;          	\
				memcpy(node,temp,sizeof(list_node_t)); 		\
				free(temp); 								\
			}else{                                          \
                list_node_t *temp = head;                   \
                while(temp -> next != node)                 \
                    temp = temp -> next;                    \
                temp -> next = NULL;                        \
				free(node);		                            \
                node = NULL;                                \
			}												\
	}

#endif
2.3单向循环链表

单向循环链表:

单向循环链表和普通的单向链表的操作逻辑几乎一样,唯一就是初始化和结尾判断有区别。

单向链表里面每一个节点的next都要有一个指向,单向循环,最后一个节点的next指向head节点

(1)初始化

//初始化链表(新建一个不带数据的头结点)
ListNode *init(void)
{
	ListNode *head = malloc(sizeof(ListNode));
	if (head != NULL)
	{
		head->next = head;
	}
	else
	{
		return NULL;
	}
	return head;
}

( 2 )、尾插法

//插入节点,尾插法
void insert_tail(ListNode *head, ListNode *new)
{
	if (head == NULL || new == NULL)
	{
		return ;
	}
	ListNode *p = head;//定义一个临时中间变量p,用来遍历链表,找到最后的节点,防止头结点地址发生改变
	while(p->next != head)
	{
		//一个一个往后找
		p = p->next;
	}
	//找到最后一个节点之后,将最后一个节点的next设置为new(新节点的地址)
	p->next = new;
	//将新的尾部节点 new的next指向 头结点
	new->next = head;
}
单向循环链表的应用 约瑟夫环问题

N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3。

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

typedef int Datatype;
typedef struct Node
{	
	Datatype data;
	struct Node *next;	
}ListNode;



ListNode * InitNode(Datatype data)	//带数据的头节点
{
	ListNode * head=(ListNode *)malloc(sizeof(ListNode));
	if(head != NULL){
		head->data = data;
		head->next = head;
	}else{
		return NULL;
	}
	return head;
}


//创建
ListNode * CreateNode(Datatype data)
{
	ListNode * new=(ListNode *)malloc(sizeof(ListNode));
	if (new!=NULL){
		new->next = NULL;
	}else{
		return NULL;
	}
	new->data = data;
	return new;
}


//尾插
void InsertNodeTail(ListNode *head,ListNode * new)
{
	ListNode *p=head;
	while(p->next!=head)
	{
		p=p->next;
	}
	p->next = new;
	new->next=head;
}


//头插
void InsertNodeHead(ListNode *head,ListNode *new)
{
	new->next = head->next;
	head->next=new;
}


void Display(ListNode *head)
{
	ListNode *p=head;
	printf("%d ",head->data);
	while(p->next!=head)
	{
		printf("%d  ",p->next->data);
		p=p->next;
	}
	printf("\n");
}

ListNode * DeleteNode(ListNode *head,ListNode *delNode)
{
	ListNode *p=head;
	while(p->next!=head)
	{
		if(p->next == delNode)
		{
			ListNode *tmp = p->next;
			p->next = tmp->next;
			free(tmp);
			tmp=NULL;
			return p->next;
		}
		p=p->next;
	}
	return NULL;
}



void ClearNode(ListNode *head)		//清空全部节点
{
	ListNode *p=head;
	if(head == NULL ||head->next ==NULL)
		return;

	while(p->next!=head)
	{
		ListNode *tmp = p->next;
		p->next = tmp->next;
		free(tmp);
		tmp->next=NULL;
		tmp=NULL;
	}
	free(head);
	head->next=NULL;
	head=NULL;
}

void GetSurvival(ListNode *head,int num,int pos)
{
	if(num == 0)
		return;
	if(num<pos)
	{
		Display(head);
		ClearNode(head);	//清空全部节点
		return;
	}
	ListNode *p=head;
	int flag=1;
	while(1)
	{
		ListNode *tmp=p;
		for(int i=1;i<pos-1;i++)	//移动节点
		{
			tmp=tmp->next;
		}
		//删除节点
		ListNode *delnode = tmp->next;
		printf("kill %d\n",delnode->data);
		tmp->next = delnode->next;
		free(delnode);
		delnode=NULL;
		// DeleteNode(p,tmp);
		p=tmp->next;
		--num;

		if(num == pos)
		{	
			for(int i=1;i<pos;i++)
			{
				if (flag)
				{
					printf("存活的人为:");
					flag=0;
				}
				printf("%d ",p->data);
				p=p->next;
			}
			printf("\n");
			ClearNode(p);	//清空全部节点
			return;
		}

	}

}

int main(int argc, char const *argv[])
{
	int num=11,pos;
	ListNode *head=NULL;

	while(1)
	{
		head = InitNode(1);
		printf("输入总人数:");
		scanf("%d",&num);
		printf("输入杀死第几个人:");
		scanf("%d",&pos);
		for(int i=2;i<=num;i++)
		{
			InsertNodeTail(head,CreateNode(i)); 
		}
		Display(head);
		GetSurvival(head,num,pos);
		if(num ==0)
			break;
		head=NULL;
	}

	return 0;
}
2.4双向循环链表

双向循环链表节点

在这里插入图片描述

节点结构体声明

typedef int Datatype;
//双向循环链表节点
typedef struct Node
{
	Datatype data;//数据域
	struct Node *prev;//前驱指针		//指针域
	struct Node *next;//后继指针
}LinkNode;

初始化

//初始化空链表
LinkNode * Init()
{
	LinkNode * head = (LinkNode *)malloc(sizeof(LinkNode));
	if(head!=NULL)
	{
		head->prev=head;
		head->next=head;
	}
	return head;
}

新建节点

//新建节点
LinkNode * CreateNode(Datatype data)
{
	LinkNode * tmp = (LinkNode *)malloc(sizeof(LinkNode));
	if(tmp == NULL)
		return NULL;
	tmp->data = data;
	tmp->prev=NULL;
	tmp->next=NULL;
	return tmp;
}

插入节点

尾插法

插入是放在尾部节点的后面,那么就相当于等于插入到头结点的前面

在这里插入图片描述

//插入节点,尾插法
void InsertNodeTail(LinkNode *head,LinkNode *newNode)
{
	LinkNode *tail = head->prev;

	newNode->prev = tail;
	newNode->next=head;
	head->prev=newNode;
	tail->next=newNode;
	return head;
}

头插法

//头插法
 void InsertNodeHead(LinkNode *head,LinkNode *newNode)
{
	LinkNode *first = head->next;

	newNode->prev=head;	//防止链表的链式关系断开
	newNode->next=first;
	first->prev=newNode;
	head->next=newNode;
	return head;
}

遍历链表

//遍历从前往后
void DisplayNegative(LinkNode *head)
{
	LinkNode *p=head;
	while(p->prev!=head)
	{
		p=p->prev;
		printf("%d ",p->data);
	}
	printf("\n");
}

//遍历从后往前
void DisplayPositive(LinkNode *head)
{
	LinkNode *p=head;
	while(p->next!=head)
	{
		p=p->next;
		printf("%d ",p->data);
	}
	printf("\n");
}

查找节点

LinkNode *FindNode(LinkNode *head,Datatype data)
{
	LinkNode *p=head;
	while(p->next!=head)
	{
		p=p->next;
		if(p->next==data)
		{
			return p;
		}
	}
	return NULL;
}

更新节点

//更新节点
void UpdateNode(LinkNode *head,Datatype old_data,Datatype new_data)
{
	LinkNode *p=FindNode(head,old_data);
	if(p!=NULL)
	{
		p->data=new_data;
		printf("修改成功\n");
	}
	else
	{
		printf("没有这个节点");
	}
}

删除节点

//删除节点
int DeleteNode(LinkNode *head,Datatype data)
{
	LinkNode *p=head;
	while(p->next!=head)
	{
		if(p->next->data==data)
		{
			LinkNode *tmp=p->next;
			p->next=tmp->next;
			tmp->next->prev=p;
			free(tmp);
			tmp->next=NULL;
			tmp->prev=NULL;
			tmp=NULL;
			return 1;
		}
		p=p->next;
	}
	return 0;
}

//判断空链表

//判断空链表
bool IsEmpty(LinkNode* head)
{
	return (head->next == head && head->prev == head);
}

//清空链表

//清空链表
void ClearLinkNode(LinkNode* head)
{
	if(head == NULL || IsEmpty(head))
	{
		return ;
	}
	while(head->next != head)
	{
		LinkNode tmp = head->next;
		head->next = tmp->next;
		tmp->next->prev = head;
		free(tmp);
		tmp->next = tmp->prev = NULL;
		tmp = NULL;
	}
}

双向循环链表 完整代码
#include <stdio.h>
#include <stdlib.h>

typedef int Datatype;

typedef struct Node
{
	Datatype data;
	struct Node *prev;
	struct Node *next;
}LinkNode;

//初始化
LinkNode * Init()
{
	LinkNode * head = (LinkNode *)malloc(sizeof(LinkNode));
	if(head!=NULL)
	{
		head->prev=head;
		head->next=head;
	}
	return head;
}

//创建节点
LinkNode * CreateNode(Datatype data)
{
	LinkNode * tmp = (LinkNode *)malloc(sizeof(LinkNode));
	tmp->data = data;
	tmp->prev=NULL;
	tmp->next=NULL;
	return tmp;
}

//尾插法
LinkNode * InsertNodeTail(LinkNode *head,LinkNode *newNode)
{
	LinkNode *tail = head->prev;

	newNode->prev = tail;
	newNode->next=head;
	head->prev=newNode;
	tail->next=newNode;
	return head;
}

//头插法
LinkNode *InsertNodeHead(LinkNode *head,LinkNode *newNode)
{
	LinkNode *first = head->next;

	newNode->prev=head;	//防止链表的链式关系断开
	newNode->next=first;
	first->prev=newNode;
	head->next=newNode;
	return head;
}

//逆序遍历
void DisplayNegative(LinkNode *head)
{
	LinkNode *p=head;
	while(p->prev!=head)
	{
		p=p->prev;
		printf("%d ",p->data);
	}
	printf("\n");
}

//正序遍历
void DisplayPositive(LinkNode *head)
{
	LinkNode *p=head;
	while(p->next!=head)
	{
		p=p->next;
		printf("%d ",p->data);
	}
	printf("\n");
}

//查找节点
LinkNode *FindNode(LinkNode *head,Datatype data)
{
	LinkNode *p=head;
	while(p->next!=head)
	{
		p=p->next;
		if(p->next==data)
		{
			return p;
		}
	}
	return NULL;
}

//更新节点
void UpdateNode(LinkNode *head,Datatype old_data,Datatype new_data)
{
	LinkNode *p=FindNode(head,old_data);
	if(p!=NULL)
	{
		p->data=new_data;
		printf("修改成功\n");
	}
	else
	{
		printf("没有这个节点");
	}
}


//删除节点
int DeleteNode(LinkNode *head,Datatype data)
{
	LinkNode *p=head;
	while(p->next!=head)
	{
		if(p->next->data==data)
		{
			LinkNode *tmp=p->next;
			p->next=tmp->next;
			tmp->next->prev=p;
			free(tmp);
			tmp->next=NULL;
			tmp->prev=NULL;
			tmp=NULL;
			return 1;
		}
		p=p->next;
	}
	return 0;
}

//判断空链表
bool IsEmpty(LinkNode* head)
{
	return (head->next == head && head->prev == head);
}

//清空链表
void ClearLinkNode(LinkNode* head)
{
	if(head == NULL || IsEmpty(head))
	{
		return ;
	}
	while(head->next != head)
	{
		LinkNode tmp = head->next;
		head->next = tmp->next;
		tmp->next->prev = head;
		free(tmp);
		tmp->next = tmp->prev = NULL;
		tmp = NULL;
	}
}
//从小到大插入
int InsertNodeOrder(LinkNode *head,LinkNode *newNode)
{
	LinkNode *p=head;
	while(p->next!=head)
	{
		if(p->next->data.price > newNode->data.price)
		{
			//头插
			InsertNodeHead(p,newNode);
			return 1;
		}
		p=p->next;
	}
	
	//尾插入
	return (InsertNodeTail(head,newNode));

}

int main(int argc, char const *argv[])
{
	int num=10;
	LinkNode *head = Init();
	for(int i=1;i<=num;i++)
	{
		// InsertNodeTail(head,CreateNode(i));
		InsertNodeHead(head,CreateNode(i));
	}	
	DisplayNegative(head);
	DisplayPositive(head);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yengi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值