C语言之.*(链表,循环链表,队列,循环队列)

一、单链表

链表:不像顺序表一样占据一段连续的内存空间,储存单元是分撒的任意的地址,每个数据都存放到链表的节点中,每个节点由指针连在一起。每个节点可以是结构体类型元素,每个节点包括指针域和数据域,其中表尾指针域置为空NULL

顺序表的优势:顺序表可以随机访问其中的元素,而链表不可以。就是因为顺序表的底层是数组,而数组是可以通过下标达到随机访问的目的。而链表只能通过指针去遍历访问。a[3] , a[8]数组可以随机访问,但是链表不可以,需要指针,索引,一个个遍历。顺序表也可以通过指针p,类似数组,p+4,p+9随机,访问数据,顺序表地址必须是挨着的。

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

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

//定义任意数据
typedef struct data
{
	char * num;
	float score;
	char name[10];
	long index;
}DataType,*P_DataType;
typedef struct node 
{
    DataType data;  // 结构体数据类型,可以是任何想要定义的类型
	struct node *next;//指向本身,结构体数据类型的指针
}Linknode,*P_LinkList;
P_LinkList CreatInitLinkHead();
int NewLinkNode_InsertToListTail(P_LinkList Head,DataType *data,int size);
int ShowLinkList(P_LinkList Head);
int InsertToLinkList_anypos(P_LinkList Head,int index, DataType *data,int size);
int Delenode2(P_LinkList Head,int index);

//插入元素,并输出,然后,任意位置插入,输出

int main()
{
	P_LinkList Head = NULL;
	int rt = -1;
	
	//1创建链表
	if(   (Head = CreatInitLinkHead()) == NULL  ) {
		printf("Creat Init LinkHead fainl \r\n");
		return -1;
	} else {
		printf("Creat Init LinkHead success \r\n");
	}
	//2插入数据
	DataType data1 = {
		.num = "zhang san",
		.index = 1,
	};
	
	DataType data2 = {
		.num = "li si",
		.index = 2,
	};
	
	DataType data3= {
		.num = "da piao liang",
		.index = 3,
	};
	
	DataType data4= {
		.num = "xiao bie san",
		.index = 4,
	};
	
    P_DataType a[4] = {&data1,&data2,&data3,&data4};
	int size = sizeof(DataType);
	int i = 0;
	for(i=0; i <4; i++) {
		rt = NewLinkNode_InsertToListTail(Head ,a[i],size);
		if(rt < 0) {
				printf("NewLinkNode_InsertToListTail fainl \r\n");
				return -1;
		}
		else {
			printf("NewLinkNode_InsertToListTail succcess \r\n");
		}
	}

    //3		输出显示链表	
	rt = ShowLinkList(Head );
	if(rt < 0) {
		printf("ShowLinkList fainl \r\n");
		return -1;
	}

	//4 随意位置插入数据
	DataType data22 = {
		.num = "li si 2 ",
		.index = 2,
	};
	
	DataType data33= {
		.num = "da piao liang 2",
		.index = 33,
	};
	
	DataType data44= {
		.num = "xiao bie san 2",
		.index = 4,
	};
	
        P_DataType aa[3] = {&data22,&data33,&data44};
	for(i=0; i <3; i++) {		
		rt = InsertToLinkList_anypos(Head ,aa[i]->index,aa[i],size);
		if(rt < 0) {
				printf("InsertToLinkList_anypos fainl \r\n");
				return -1;
		}
		else {
			printf("InsertToLinkList_anypos succcess \r\n");
		}
	}


	//5,重新输出显示数据			
	rt = ShowLinkList(Head );
	if(rt < 0) {
		printf("ShowLinkList fainl \r\n");
		return -1;
	}

	return 0;
}

//,创建链表,定义一个结构体类型指针函数,此函数返回一个指针

P_LinkList CreatInitLinkHead()
{
	P_LinkList Head = NULL;

	if(   (Head =(P_LinkList)malloc(sizeof(Linknode))) == NULL  ) {
		return Head ;
	}
	
	//Head ->data =0;
	Head ->next = NULL;
	return Head ;
}

//新建节点插入头部

int NewLinkNode_InsertToListHead(P_LinkList Head,DataType *data,int size) {

	if(Head ==NULL) {
		printf("NewLinkNode_InsertToListHeadHead is null \r\n");
		return -1;
	}
	
	P_LinkList Pnode= NULL;

	if( (Pnode=(P_LinkList)malloc(sizeof(Linknode))) == NULL  ) {
		printf("NewLinkNode_InsertToListHeadmalloc fail\r\n");
		return -1;
	} 
	
	memcpy(&(Pnode->data),data,size);
	Pnode->next = Head->next;	
	Head->next = Pnode;
	
	return 0;
}

//新建节点插入尾部

int NewLinkNode_InsertToListTail(P_LinkList Head,DataType *data,int size) {

	if(Head == NULL) {
		printf("NewLinkNodeToListfail  Head is null \r\n");
		return -1;
	}
	
	P_LinkList Pnode = NULL;
	Pnode = Head ;
	while(Pnode->next != NULL) {   //或//while(Pnode->next)
		Pnode = Pnode->next;
	}
	
	P_LinkList Pnode2 = NULL;
	if( (Pnode2=(P_LinkList)malloc(sizeof(Linknode))) == NULL  ) {
		printf("NewLinkNodeToListmalloc fail\r\n");
		return -1;
	} 
	
	memcpy(&(Pnode2->data),data,size);
	Pnode->next = Pnode2;	
	Pnode2->next = NULL;
	
	return 0;
}

//新建节点插入任意位置

int InsertToLinkList_anypos(P_LinkList Head,int index, DataType *data,int size) {

	if(Head == NULL) {
		printf("InsertToLinkList fail  Head is null \r\n");
		return -1;
	}

	P_LinkList Pnode= NULL;
	Pnode = Head ;

	while(Pnode->next != NULL) {   //或//while(Pnode->next)
		if(Pnode->data.index == index)
			break;
		Pnode = Pnode->next;
	}

	P_LinkList Pnode2= NULL;

	if( (Pnode2 =(P_LinkList)malloc(sizeof(Linknode))) == NULL  ) {
		printf("InsertToLinkList malloc fail\r\n");
		return -1;
	} 
	
	memcpy(&(Pnode2->data),data,size);
	Pnode2->next = Pnode->next;
	Pnode->next = Pnode2;

	return 0;
}

//输出链表所有元素

int ShowLinkList(P_LinkList Head)//定义一个输出链表函数
{
	if(Head == NULL) {
		printf("Head is null \r\n");
		return -1;
	} else {
		P_LinkList Pnode= NULL;
		Pnode = Head ;
		
		do
		{
			printf("%d:%s ->\n",Pnode->data.index,Pnode->data.num);
			Pnode  = Pnode ->next;
		}while(Pnode !=NULL);//直到表尾
	}
	return 0;
}

//删除节点函数1,知道节点的指针

void delenode(linklist *list, linklist q)
{
	linklist ptr;
	if(q == list)//如果删除的是第一个表头位置节点
	{
		*list = q->next//表头指针域赋给表头指针;
		free(q);//释放指针
	}
	else
	{
		for(ptr = list; ptr->next!=q; ptr = ptr->next/*后驱的指针放在了前驱的指针域里*/);//遍历链表找到相应节点指针
		if(ptr->next !=NULL)//没有出到表尾
		{
		ptr->next =q->next;//直接把要删除节点指针域赋给前驱节点指针域
		free(q);//释放这个节点得指针
		}
	}
}

//删除节点函数2

int Delenode2(P_LinkList Head,int index)
{
	if(Head == NULL) {
		printf("Delenodefail  Head is null \r\n");
		return -1;
	}

	P_LinkList Pnode = NULL;
	Pnode = Head ;
	
	if(Head->data.index == index)//如果删除的是第一个表头位置节点
	{
		Pnode = Head->next;
		free(Head);
		Head = Pnode;
	}

	while(Pnode->next != NULL && (Pnode->next->data.index != index)) {
		Pnode = Pnode->next;
	}

	if(Pnode->next->data.index == index)// 必须找到了,才能去删除
	{
		P_LinkList delPnode = Pnode->next;
		Pnode->next = Pnode->next->next;		
		free(delPnode);
	}
	
	return 0;
}

//销毁链表函数

void Destory(P_LinkList Head )
{
	if(Head ==NULL) {
		printf("Head is null \r\n");
		return -1;
	}
	
	P_LinkList Pnode = NULL;
	Pnode = Head ;
	while(Pnode->next != NULL) {   //或//while(Pnode->next)
		Head = Pnode->next;
		free(Pnode );
		Pnode = Head ;
	}//直到最后一个指针
        
	free(Pnode);
	Head = NULL;
}

输出结果
在这里插入图片描述
本例子中index,作为索引,方便查找,插入位置,但是如果数据过于庞大,不能采用最好,修改后面所有的index,时间会很长,看用在什么场景。本文没有给出修改index的操作

删除链表节点后
Delenode2(Head,2);
Delenode2(Head,33);
Delenode2(Head,4);
在这里插入图片描述

2、第二种写法

#include<stdio.h>

typedef int elemtype;

typedef struct node{
      elemtype date//数据域;
	  struct node *next;//指向结构体型指针域
}lnode,*linklist;//这里定义了两个变量,一个普通结构体类型数据变量,一个指向结构体的指针变量,后面定义的指针都为这类型

linknode Creatlink(int n)//定义一个返回指针的函数      与上个例子相似
{
	linknode p1,p2,head = null;//定义指针变量
	int i;
	elemtype elem;
	for(i = 1; i < n; i++)//建立n个节点的链表
	{
		scanf("%d",&elem);//输入数据域
		p1 = (linklist)malloc(sizeof(lnode));
		p1->date = elem;
		p1->next = NULL;
		if(!head)
			head = p1;//如果为是第一个表则把第一个节点的指针赋给头指针
        else
			p2->next = p1;//后驱的指针赋给前驱指针域
		p2 = p1;//前驱指针换为后驱指针
	}
return (head);
}

void insertnode(linklist *list, linklist q, elemtype elem)//定义一个插入节点函数
{
	linklist ptr;
	ptr = (linklist)malloc(sizeof(elemtype));
	ptr->date = elem;
	if(!list)//如果只有一个节点空表
	{
		*list = ptr;//赋给头指针
		ptr->next = NULL;
	}
    else
	{
       	ptr->next = q->next;//只需把要插入的位置的指针域赋给新建的节点的指针域
	    q->next = ptr;//新建的指针赋给要插入得位置节点指针域 
	}
}

int head_insert() {



}

void delenode(linklist *list, linklist q)//定义一个删除节点函数
{
	linklist ptr;
	if(q == list)//如果删除的是第一个表头位置节点
	{
		*list = q->next//表头指针域赋给表头指针;
		free(q);//释放指针
	}
	else//删除的是表头后节点
	{
		for(ptr = list; ptr->next!=q; ptr = ptr->next/*后驱的指针放在了前驱的指针域里*/);//遍历链表找到相应节点指针
		if(ptr->next !=NULL)//没有出到表尾
		{
		ptr->next =q->next;//直接把要删除节点指针域赋给前驱节点指针域
		free(q);//释放这个节点得指针
		}
	}
}

void Destory(linklist *list)//销毁链表函数
{
	linklist p, q;
	p = *list;//从表头开始
	while(p)//直到表尾
	{
		q = p->next;//前驱的指针域赋给后节点得指针
        free(p);
		p = q;//重新指向这个节点
	}
    *list = NULL;//最后需制空。防止野指针
}
main()//主函数
{
    int elem, i;
	linklist L,q;//定义一张表
	q = L = Creatlink(1);//调用建表函数并获得表头指针
	scanf("%d",&elem);输入数据
	while(elem)//用于判断结束循环。当输入位0时结束
	{
		insertnode(&L, q,elem);//调用插入函数
		q = q->next;//不断或得前驱的指针域以逻辑上各节点连接起来
		scanf("%d",&elem);//不断输入元素
	}

	q = L;//或得表头指针
	printf("the content of the linklist\n");
    while(q)//直到表尾空指针
	{
		printf("%d ",q->date);//输出数据
		q = q->next;//循环获得后驱的指针
	}
    
	printf("\n");
	q = L;//获得表头地址指针
    printf("the content of the deleay linklist\n");
	for(i = 0; i < 4; i++)//循环5次获得第5个节点的指针域
	{
		q = q->next;//获得要删除节点的指针域
	}
	delenode(&L, q);//调用删除节点函数

	q = L;
	while(q)//直到表尾
	{
		printf("%d ",q->date);//输出表  / *这里的输出可以定义一个如上例的输出函数
		q = q->next;
	}
	
	printf("\n");
	Destory(&L);//最后销毁表
	getche();
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值