所谓静态链表,就是用数组描述的链表,在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.私人观点:静态链表较动态链表难以理解。看了很长时间才懂插入操作,我人麻了,动态就很简单嘛(大雾);