静态链表:
1.静态链表和动态链表的区别:
静态链表要预先申请一整块足够内存的空间,其能存储的元素个数在创建的那一刻就不能再更改了。
动态链表:之前实现的单链表,双链表,循环链表都属于动态链表,可以在使用过程中动态申请内存。
2.静态链表是一种用数组描述的链表,其实是为了给没有指针的高级语言设计的一种实现单链表功能的方法(大话数据结构)。
3.静态链表其实包括两个链表,一个是数据链表,一个是空闲链表。
3.静态链表的第一个节点和最后一个节点作为特殊元素处理,
第一个节点作为备用链表的表头,其cur值指向下一个空闲的节点。
最后一个节点作为数据链表的表头,其cur值指向第一个有数据的节点。
4.优点:在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进在顺序存储结构中插入和删除元素需要移动大量元素的缺点
缺点:没有解决连续存储分配带来的表长难以确定的问题。
5.注意静态链表的删除操作,删除操作要更新两个链表,数据链表要更新前一节点的cur,
空闲链表要把空出的节点放入空闲链表的第一个节点(不能放入空闲链表的末尾,因为找不到空闲链表的末尾),大话数据结构也是放入空闲链表的第一个位置
静态链表C语言实现:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h> //signal()
#include<string.h>
#include<sys/stat.h>
#include<time.h>
#include<stdarg.h>
#if 1
#define INFO_DEBUG "%d lines in "__FILE__", complie time is "__TIME__" "__DATE__" \n",__LINE__
#define ADI_RUN_ERROR 1
#define ADI_NULL_POINTER -1
#define ADI_OK 0
#define ADI_PRINT printf("[%s][%d]:",__FUNCTION__,__LINE__);printf
#define ADI_ASSERT(c,prt,ret) if(c) {printf(prt);return ret;}
#endif
typedef struct list{
int elem;
int cur;//静态链表中把这个称为游标(cursor)
}list;
#define PARAM_FAIL -1
#define P_NULL -2
#define SUCCESS 0
#define LIST_SIZE 10
/*初始化:只创建头结点*/
list* initList(int size)
{
int i = 0;
list *head = (list*)malloc(size*sizeof(list));
if(NULL==head) {printf("NULL");return head;}
for(i=0;i<(size-1);i++)
{
head[i].cur = i+1;//此时整个链表都是空闲链表,注意这里不能用head[i]->cur = i+1 会报错
}
head[i].cur = 0;/*目前静态链表为空,最后一个元素的cur为0*/
return head;
}
/*销毁链表,销毁和初始化成对使用*/
int destoryList(list* list_destory)
{
if(NULL==list_destory) {printf("NULL");return PARAM_FAIL;}
free(list_destory);
return SUCCESS;
}
/*pos从0开始,pos=0为第一个*/
int insertList(list list_insert[],int elem,int pos,int list_size)
{
int i=0,empty_id=0,cur=0,last_cur=0;
if((NULL == list_insert)&& (pos>(list_size-2)) )//最后一个元素作为特殊节点不容纳元素,则支持的插入位置要减2 比如size=10,最大支持的pos=8
{
ADI_PRINT("err param\n");
return PARAM_FAIL;
}
/*取数据链表的表头*/
list head_data = list_insert[list_size-1];//不能用 list *head_data = list_insert[list_size-1];,会报错
cur = list_size-1;//cur的初始值要=list_size-1注意
while(i<pos)
{
last_cur = cur;
cur = head_data.cur;
head_data = list_insert[cur];
i++;
}
/*取空闲链表的表头list_insert[0]*/
empty_id = list_insert[0].cur;//拿到第一个空闲位置
list_insert[empty_id].elem = elem;
list_insert[0].cur = list_insert[0].cur+1;//空闲位置指向下一个位置
list_insert[empty_id].cur = list_insert[last_cur].cur;
list_insert[last_cur].cur = empty_id;
ADI_PRINT("insert elem = %d\n",elem);
return SUCCESS;
}
/*删除操作要更新两个链表,数据链表要更新前一节点的cur,
空闲链表要把空出的节点放入空闲链表的第一个节点(不能放入空闲链表的末尾,因为找不到空闲链表的末尾),大话数据结构也是放入空闲链表的第一个位置*/
int delList(list list_del[],int elem,int list_size)
{
int i=0,empty_id=0,cur=0,ele=0,last_cur=0;
if(NULL == list_del)
{
ADI_PRINT("err NULL\n");
return P_NULL;
}
/*取数据链表的表头*/
list head_data = list_del[list_size-1];//不能用 list *head_data = list_insert[list_size-1];,会报错
cur = head_data.cur;
last_cur = list_size-1;
while((list_del[cur].elem != elem)&&(0 != cur))
{
last_cur = cur;
cur = list_del[cur].cur;
}
/*能找到,cur就是待删除元素在链表中的位置*/
if(0 != cur)
{
//ADI_PRINT("elem cur = %d\n",cur);
list_del[last_cur].cur = list_del[cur].cur;//将上一个数据节点的cur进行修改
list_del[cur].cur = list_del[0].cur;
list_del[cur].elem = 0;
/*取空闲链表的表头list_insert[0],将被删除的元素放入空闲链表的第一个元素*/
list_del[0].cur = cur;
}
else
{
ADI_PRINT("can not find ele = %d\n",elem);
return PARAM_FAIL;
}
ADI_PRINT("del elem = %d\n",elem);
return SUCCESS;
}
int printList(list list_prt[],int list_size)
{
if(NULL == list_prt)
{
ADI_PRINT("err NULL\n");
return P_NULL;
}
int i = 0;
/*取数据链表的表头,按数据排布的顺序*/
#if 0
list head_data = list_prt[list_size-1];
//ADI_PRINT("head_data.cur = %d\n",head_data.cur);
while(head_data.cur)
{
head_data = list_prt[head_data.cur];
//ADI_PRINT("head_data.cur = %d\n",head_data.cur);
ADI_PRINT("list[%d] = %d\n",i,head_data.elem);
i++;
}
#endif
#if 1
/*全部打印,按数组0-max顺序*/
for(int i=0;i<list_size;i++)
{
ADI_PRINT("list[%d].ele=%d,list[%d].cur=%d\n",i,list_prt[i].elem,i,list_prt[i].cur);
}
#endif
return SUCCESS;
}
int main()
{
int ret = 0,pos = 0;
list *list_test = initList(LIST_SIZE);
if(NULL == list_test)
{
ADI_PRINT("err \n");
return P_NULL;
}
printList(list_test,LIST_SIZE);
ret = insertList(list_test,0,0,LIST_SIZE);
if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
ret = insertList(list_test,3,1,LIST_SIZE);
if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
ret = insertList(list_test,5,2,LIST_SIZE);
if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
ret = insertList(list_test,7,3,LIST_SIZE);
if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
ret = insertList(list_test,9,4,LIST_SIZE);
if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
printList(list_test,LIST_SIZE);
ret = insertList(list_test,8,4,LIST_SIZE);
if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
printList(list_test,LIST_SIZE);
ret = delList(list_test,3,LIST_SIZE);
if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
ret = delList(list_test,7,LIST_SIZE);
if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
ret = delList(list_test,9,LIST_SIZE);
if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
printList(list_test,LIST_SIZE);
return SUCCESS;
}