数据结构---链表

STL中要用到顺序结构

以双链表为例,了解基本的增删改查操作

#ifndef __CIRCLEBOTHWAYLINKEDLISTWITHHEAD_H__
#define __CIRCLEBOTHWAYLINKEDLISTWITHHEAD_H__


typedef int ElemType;	//数据元素中数据的类型
typedef struct node				//数据节点的类型
{
	ElemType data;			//数据域 --》存储数据
	struct node *next;	//指针域 --》保存逻辑上的下一个
	struct node *prev;				//保存逻辑上的上一个
}DNODE;

typedef struct List		//头节点的类型
{
	struct node * first;		//指向第一个节点
	struct node * last;			//指向最后一个节点
	int node_num;				//保存数据节点的个数
}DLIST;



struct List* create_bothway_Circle_list();                                  //创建双向循环链表

void print_bothway_Circle_list(struct List *list);                         //打印双向循环链表
 
struct List * add_a_node(struct List * list, ElemType x, ElemType a);     //增加节点
 
struct List * create_sort_bothway_Circle_list();					      //排序创建链表

struct List * delete_all_node(struct List * list, ElemType x);           //删除节点

struct List * update_node(struct List * list, ElemType x,ElemType a);    //查找并修改节点

void destroy_list(struct List ** list);                                  //销毁链表

  


#endif
#include "CircleBothwayLinkedListWithHead.h"
#include <stdio.h>
#include <stdlib.h>


/*
	根据用户的输入顺序,创建一个双向循环链表,将新链表返回
		并打印输出
*/	
struct List * create_bothway_Circle_list()
{
	//1.创建一个头结点,并初始化
	struct List *list = malloc(sizeof(struct List));
	list->first = NULL;
	list->last = NULL;
	list->node_num = 0;

	ElemType d;					//保存从键盘上获取的数据
	struct node *pnew = NULL;	//指向新创建的数据节点
	
	while(1)
	{
		//2.从键盘上获取数据
		scanf("%d", &d);
		if(d == 0)		//人为约定,输入0结束
		{
			break;
		}
		
		//3.并创建数据节点,把数据写入到新创建的数据节点中
		pnew = malloc(sizeof(struct node));
		pnew->data = d;
		pnew->next = NULL;
		pnew->prev = NULL;

		//4.把新节点 添加到 双向链表中
		if(list->first == NULL)		//从无到有
		{
			list->first = pnew;
			list->last = pnew;
		}
		else		//从少到多
		{
			//尾插法
			list->last->next = pnew;
			pnew->prev = list->last;
			list->last = pnew;
			
			//头插法
			//pnew->next = list->first;
			//list->first->prev = pnew;
			//list->first = pnew;
		}
		list->node_num ++;
	}
	
	//5.首尾相连
	if(list->node_num != 0)
	{
		list->last->next = list->first;
		list->first->prev = list->last;
	}
	
	//6.返回新创建的链表的头结点
	return list;
}




//打印链表
void print_bothway_Circle_list(struct List *list)
{
	if(list == NULL)
	{
		printf("list is NULL !\n");
		return;
	}
		
	struct node * p = list->first;		//正向
	int n = list->node_num*2;
	while(n--)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	putchar('\n');
	
	printf("======================================\n");

	p = list->last;					//逆向
	n = list->node_num*2;
	while(n--)
	{
		printf("%d ", p->data);
		p = p->prev;
	}
	putchar('\n');
	printf("======================================\n");
}



/*
	查找值为x的节点,在x的前面加入一个值为a的节点,
		如果没有找到x,就把a添加到末尾,将新链表返回 
*/				
struct List * add_a_node(struct List * list, ElemType x, ElemType a)
{
	//1.创建一个新的节点,保存a
	struct node *pnew = malloc(sizeof(struct node));
	pnew->data = a;
	pnew->next = NULL;
	pnew->prev = NULL;
	
	//2.找到值为x的节点   遍历(定义一个遍历指针)
	struct node * p = list->first;		//遍历指针
	int n = list->node_num;
	while(n--)
	{
		if(p->data == x)
		{
			break;
		}
		p = p->next;
	}

	if(n != -1 )
	{
		//3.找到了 就把新节点a插入
		if(p == list->first)
		{
			//头插
			pnew->next = list->first;
			list->first->prev = pnew;
			list->first = pnew;
		}
		else
		{
			//中间插入,先赋值pnew的成员,再去修复前后的链接
			pnew->next = p; 
			pnew->prev = p->prev;
			p->prev->next = pnew;
			p->prev = pnew;
		}
	}
	else 
	{
		//4.没有找到了  尾插法
		if(list->first == NULL)	//空链表
		{
			list->first = pnew;
			list->last = pnew;
		}
		else
		{
			//尾插
			list->last->next = pnew;
			pnew->prev = list->last;
			list->last = pnew;
		}
		
	}
	list->node_num ++;
	
	//5.首尾相连
	if(list->node_num != 0)
	{
		list->last->next = list->first;
		list->first->prev = list->last;
	}
	
	//6.将新链表返回
	return list;
}



/*
	创建一个有序的双向循环链表,将新链表返回
*/
struct List * create_sort_bothway_Circle_list()
{
	//1.创建一个头结点,并初始化
	struct List *list = malloc(sizeof(struct List));
	list->first = NULL;
	list->last = NULL;
	list->node_num = 0;

	ElemType d;					//保存从键盘上获取的数据
	struct node *pnew = NULL;	//指向新创建的数据节点
	
	while(1)
	{
		//2.从键盘上获取数据
		scanf("%d", &d);
		if(d == 0)		//人为约定,输入0结束
		{
			break;
		}
		
		//3.创建数据节点,把数据写入到新创建的数据节点中
		pnew = malloc(sizeof(struct node));
		pnew->data = d;
		pnew->next = NULL;
		pnew->prev = NULL;

		//4.把新节点 添加到 双向链表中
		if(list->first == NULL)		//从无到有
		{
			list->first = pnew;
			list->last = pnew;
		}
		else		//从少到多
		{
			/*
				分情况讨论:
					比第一个节点还要小,头插
					比最后一个节点还要大,尾插
					中间插入,找到第一个比它大的节点的前面进行插入
						//中间插入,先赋值pnew成员,再去修复前后的链接
			*/
			struct node *p = list->first;		//遍历指针
			while(p)
			{
				if(p->data > pnew->data)
				{
					break;
				}
				p = p->next;
			}

			if(p == NULL)		//没有找到,尾插
			{
				list->last->next = pnew;
				pnew->prev = list->last;
				list->last = pnew;
			}
			else			//找到了
			{
				if(p == list->first)	//第一个,头插
				{
					pnew->next = list->first;
					list->first->prev = pnew;
					list->first = pnew;
				}
				else		//中间插入
				{
					//先赋值pnew成员,再去修复前后的链接
					pnew->next = p;
					pnew->prev = p->prev;
					p->prev->next = pnew;
					p->prev = pnew;
				}
			}
			
		}
		list->node_num ++;
	}

	//5.首尾相连
	if(list->node_num != 0)
	{
		list->last->next = list->first;
		list->first->prev = list->last;
	}
	
	//6.返回新创建的链表的头结点
	return list;
}



/*
	在链表中找到值为x的节点,将其全部删除
		若没有找到 就不删除,将新链表返回
*/
struct List * delete_all_node(struct List * list, ElemType x)
{
	//1.找到值为x的节点
	struct node *p = list->first;		//遍历指针

	int n = list->node_num;
	while(n--)
	{
		if(p->data == x)
		{
			//2.找到了,删除
				/*
					分情况讨论:
						删除第一个节点
						删除最后一个节点
						删除中间节点
							//删除中间节点,先把前后的链接修复,再去断开自身的链接
				*/
			list->node_num --;

			if(p == list->first)	//删除第一个节点
			{
				list->first = list->first->next;
				if(list->first != NULL)
				{
					list->first->prev = NULL;
				}
				p->next = NULL;
				p->prev = NULL;
				free(p);
				p = list->first;

				if(list->first == NULL)	//最后一个节点也被删除了
				{
					list->last = NULL;
				}
			}
			else if(p == list->last)	//删除最后一个节点
			{
				list->last = list->last->prev;
				list->last->next = NULL;
				p->prev = NULL;
				free(p);
				p = NULL;
			}
			else			//删除中间节点
			{
				struct node * temp = p->next;
				
				//先把前后的链接修复,再去断开自身的链接
				p->prev->next = p->next;
				p->next->prev = p->prev;
				p->next = NULL;
				p->prev = NULL;
				free(p);

				p = temp;
			}
		}
		else
		{
			//3.没有找到,就继续往下找
			p = p->next;
		}
	}

	//4.首尾相连
	if(list->node_num != 0 )
	{
		list->last->next = list->first;
		list->first->prev = list->last;
	}
	
	//5.返回新链表的头结点
	return list;
}




/*
	在链表中查找值为x的节点,将所有值为x的节点修改成a
		如果没有找到,则不修改, 将新链表返回 
	
*/
struct List * update_node(struct List * list, ElemType x,ElemType a)
{
	struct node * p = list->first;		//遍历指针

	int n = list->node_num;
	while(n--)
	{
		if(p->data == x)
		{
			p->data = a;
		}
		p = p->next;
	}
	return list;
}




//销毁一条链表
void destroy_list(struct List ** list)
{
	struct node * p = (*list)->first;		//遍历指针

	int n = (*list)->node_num;
	while(n--)
	{
		(*list)->first = p->next;
		if((*list)->first != NULL)
		{
			(*list)->first->prev = NULL;
		}
		p->next = NULL;
		free(p);

		p = (*list)->first;
	}
	(*list)->node_num = 0;
	(*list)->last = NULL;
	free(*list);
	
	*list = NULL;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值