静态链表的认知

所谓静态链表,就是用数组描述的链表,在C语言中,静态链表的表现形式即为结构体数组,结构体变量包括数据域和游标。

1.静态链表的定义

typedef struct SLinkedNode{  //静态链表的定义 
	int data;  //数据 
	int next;  //指针 
} *NPtr, LNode;

typedef struct SLinkList{ //套娃啊啊啊 
	NPtr nodes;
	int* used;
}*LPtr; 

2.静态链表的初始化

LPtr initLinkList(){   //静态链表的初始化 
	LPtr temp = (LPtr)malloc(sizeof(SLinkList));   // 申请空间 
	
	temp->nodes = (NPtr)malloc(sizeof(LNode) * SIZE); //申请空间 
	temp->used = (int*)malloc(sizeof(int) * SIZE); //申请空间 
	
	temp->nodes[0].data = 0;  //定义头节点 
	temp->nodes[0].next = -1;  
	
	temp->used[0] = 1; //用过了
	for(int i = 1; i < SIZE; i++){
		temp->used[i] = 0;//赋值0证明没有用过 
	}
	
	return temp; 
}

3.静态链表的打印

void printList(LPtr paraLPtr)
{
	int p = 1; //从头节点开始 
	while(p != -1)
	{
		printf("%d", paraLPtr->nodes[p].data);
		p = paraLPtr->nodes[p].next; //到结尾时会赋值-1就停下来了 
	}
	printf("\n");
}

4.静态链表的插入

void insertElement(LPtr paraLPtr, int paraData, int paraPosition){
	int p, q, i;
	
	//判断位置合法性
	if(paraPosition < 0 || paraPosition > SIZE)
	{
		printf("位置没有负数亦或者位置大于了整体大小,%d插不进去!\n", paraData);
		return;
	}
	p = 0;
	for(i = 0; i < paraPosition; i++)
	{
		p = paraLPtr->nodes[p].next;//第二轮走这里,p = 1,不会再循环 
		if(p == -1)
		{
			printf("插入的位置太后面了%d插不进去!\n", paraData);  //这是有位置,但比如10大小,只有3个元素,你要插到第五个位置就不行 
			return;
		}
	}
	
	for (i = 1; i < SIZE; i ++)
	{
		if(paraLPtr->used[i] == 0)//从头遍历到used[i] == 0的位置,证明了到此位置还没被用过
		{
			printf("有位置且合理,%d插进去了\n", paraData);
			paraLPtr->used[i] = 1; //用过啦!
			q = i; //把i给q
			break; 
		}
	}
	
	if(i == SIZE){
		printf("no space!\n");
		return; 
	}
	
	paraLPtr->nodes[q].data = paraData;
	
	printf("linking!\n");
	paraLPtr->nodes[q].next = paraLPtr->nodes[p].next; //接 
	paraLPtr->nodes[p].next = q; //再接 
	 
}

 这个图,好好理解一下,就知道什么是静态链表了,e1的后面是e2,所以是3,这样才能跟到2后面,

5.删除,删除!

void deleteElement(LPtr paraLPtr, int paraData){   //删除一个元素 
	int p, q;
	p = 0;
	while((paraLPtr->nodes[p].next != -1) && (paraLPtr->nodes[paraLPtr->nodes[p].next].data != paraData)){
		p = paraLPtr->nodes[p].next;
		
	}
	if(paraLPtr->nodes[p].next == -1){
		printf("不能删%d", paraData);
		return;
	}
	
	q = paraLPtr->nodes[p].next;
	paraLPtr->nodes[p].next = paraLPtr->nodes[paraLPtr->nodes[p].next].next;  //套娃,带入单链表删除的话比较容易理解 
	
	paraLPtr->used[q] = 0; //好,我又成为没有被使用的状态啦! 
}

6.总代码

#include<stdio.h> 
#include<malloc.h>
#define SIZE 10
#define isMyFaith main
typedef int Kurumi; //夹带私货 

typedef struct SLinkedNode{  //静态链表的定义 
	int data;  //数据 
	int next;  //指针 
} *NPtr, LNode;

typedef struct SLinkList{ //套娃啊啊啊 
	NPtr nodes;
	int* used;
}*LPtr; 

LPtr initLinkList(){   //静态链表的初始化 
	LPtr temp = (LPtr)malloc(sizeof(SLinkList));   // 申请空间 
	
	temp->nodes = (NPtr)malloc(sizeof(LNode) * SIZE); //申请空间 
	temp->used = (int*)malloc(sizeof(int) * SIZE); //申请空间 
	
	temp->nodes[0].data = 0;  //定义头节点 
	temp->nodes[0].next = -1;  
	
	temp->used[0] = 1; //用过了
	for(int i = 1; i < SIZE; i++){
		temp->used[i] = 0;//赋值0证明没有用过 
	}
	
	return temp; 
}

void printList(LPtr paraLPtr)
{
	int p = 1; //从头节点开始 
	while(p != -1)
	{
		printf("%d", paraLPtr->nodes[p].data);
		p = paraLPtr->nodes[p].next; //到结尾时会赋值-1就停下来了 
	}
	printf("\n");
}

void insertElement(LPtr paraLPtr, int paraData, int paraPosition){
	int p, q, i;
	
	//判断位置合法性
	if(paraPosition < 0 || paraPosition > SIZE)
	{
		printf("位置没有负数亦或者位置大于了整体大小,%d插不进去!\n", paraData);
		return;
	}
	p = 0;
	for(i = 0; i < paraPosition; i++)
	{
		p = paraLPtr->nodes[p].next;//第二轮走这里,p = 1,不会再循环 
		if(p == -1)
		{
			printf("插入的位置太后面了%d插不进去!\n", paraData);  //这是有位置,但比如10大小,只有3个元素,你要插到第五个位置就不行 
			return;
		}
	}
	
	for (i = 1; i < SIZE; i ++)
	{
		if(paraLPtr->used[i] == 0)//从头遍历到used[i] == 0的位置,证明了到此位置还没被用过
		{
			printf("有位置且合理,%d插进去了\n", paraData);
			paraLPtr->used[i] = 1; //用过啦!
			q = i; //把i给q
			break; 
		}
	}
	
	if(i == SIZE){
		printf("no space!\n");
		return; 
	}
	
	paraLPtr->nodes[q].data = paraData;
	
	printf("linking!\n");
	paraLPtr->nodes[q].next = paraLPtr->nodes[p].next; //接 
	paraLPtr->nodes[p].next = q; //再接 
	 
}

void deleteElement(LPtr paraLPtr, int paraData){   //删除一个元素 
	int p, q;
	p = 0;
	while((paraLPtr->nodes[p].next != -1) && (paraLPtr->nodes[paraLPtr->nodes[p].next].data != paraData)){
		p = paraLPtr->nodes[p].next;
		
	}
	if(paraLPtr->nodes[p].next == -1){
		printf("不能删%d", paraData);
		return;
	}
	
	q = paraLPtr->nodes[p].next;
	paraLPtr->nodes[p].next = paraLPtr->nodes[paraLPtr->nodes[p].next].next;  //套娃,带入单链表删除的话比较容易理解 
	
	paraLPtr->used[q] = 0; //好,我又成为没有被使用的状态啦! 
}

void appendInsertDeleteTest(){
	LPtr tempList = initLinkList(); //创建链表! 

	insertElement(tempList, 5, 0);
	insertElement(tempList, 7, 1);
	insertElement(tempList, 0, 2);
	insertElement(tempList, 4, 3);
	insertElement(tempList, 9, 4);
	printList(tempList);


	printf("Deleting '7'.\r\n");
	deleteElement(tempList, 7);
	printf("Deleting '4'.\r\n");
	deleteElement(tempList, 4);
	printf("Deleting '9'.\r\n");
	deleteElement(tempList, 9);
	printList(tempList);

	insertElement(tempList, 5, 1);
	printList(tempList);
}

Kurumi isMyFaith()
{
	appendInsertDeleteTest();
	
	return 0;
 } 

运算结果

有位置且合理,5插进去了
linking!
有位置且合理,7插进去了
linking!
有位置且合理,0插进去了
linking!
有位置且合理,4插进去了
linking!
有位置且合理,9插进去了
linking!
57049
Deleting '7'.
Deleting '4'.
Deleting '9'.
50
有位置且合理,5插进去了
linking!
550

静态链表和动态表的差距:

1.静态用数组,动态表不用,

2.静态链表我觉得用处不大,长度大小锁死,单链表是动态的,要多大有多大

3.静态链表插入和删除时不需要移动元素,仅需修改指针。而动态链表需要指针去顺序访问;

4.私人观点:静态链表较动态链表难以理解。看了很长时间才懂插入操作,我人麻了,动态就很简单嘛(大雾);

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值