链表的游标法实现 cursor_list-建立自己的c数据结构与算法库系列(6)

实现思路:链表的各个节点预先存放在一个节点数组中 ,每个节点的"next"是一个整数,代表下一个节点在节点数组中的位置。
优缺点:由于不需要动态内存分配置,此链表比文章(5)中的链表实现快,但是需要预先估计链表的大小,防止链表太大时没有节点可分配。
额外操作:在使用游标链表前,需要一个循环把节点数组“串连”起来。
关键问题:
A:怎么样表示一个节点?
Q:以数组的下标表示一个节点
假如数组下标为n,则CursorSpace[n]表示此实际节点
A:怎么样表示next指针?
Q:以数组下标代替指针。
假如n表示节点,则CursorSpace[n].next表示下一个指向的节点(next就是一个数组下标)
实现关键有几点:
1。需要一个全局的节点数组CursorSpace[](不是动态分配),节点定义如:
struct Cur_Node
{
  Cur_Element e;
  Cur_Position next;
};
  Cur_Position 定义为整数,代表下一个节点的数组的下标
2。需要实现一个CursorAlloc()分配游标,定义一个CursorFree回收游标。
3。链表使用前需要初始化节点数组,以开成一个“分配链”

节点数组初始化如图1:

4。解决了用下标“模拟”next指针这个问题后,其它的实现就和一般链表的实现一样,可以看到,cur_list.h和”文章(5)“中的list.h几乎一模一样,只是为了区别每个函数加了cur_前缀

                        图1 
   调用一次CursorAlloc实际上等于分配第0个节点指向的下一个节点,假如前三个可分配节点为:n0 ,nx,ny,那么本次分配表示如下:
   n0.next=nx.next
   return x
   如果x=0,说明已经没有节点可分配,否则CursorSpace[x]就是分配到的节点,当然CursorSpace应该是被封装起来的,在头文件中看不到。
   从图1中的节点调用一次CursorAlloc节点1被分配分去,如下图所示:
     


ADT cur_list.h:
/**********************************
*author:Felix
*last update:Sun Jan 6 12:33:03 EST 2008
*description:
*
*
*
*/
#ifndef ___LIST___
#define ___LIST___
#include<stdio.h>
#include<stdlib.h>
/*define MAX_CURSOR_SIZE to decide the cursor size*/
#ifndef ___MAX_CURSOR_SIZE___
  #define MAX_CURSOR_SIZE 1024
#define __MAX_CURSOR_SIZE___
#endif

struct Cur_Node;
typedef int Cur_PtrNode;
typedef Cur_PtrNode Cur_List;
typedef Cur_PtrNode Cur_Position;
typedef int Cur_Element;

void cur_InitializeCursor();

Cur_List cur_MakeEmpty();
int cur_IsEmpty(Cur_List l);
int cur_IsLast(Cur_Position p);
Cur_Position cur_Find(Cur_Element e,Cur_List l);
void cur_Delete(Cur_Element e,Cur_List l);
Cur_Position cur_FindPrevious(Cur_Element e,Cur_List l);
Cur_Position cur_Insert(Cur_Element e,Cur_List l,Cur_Position p);
void cur_DeleteList(Cur_List l);
Cur_Position cur_Header(Cur_List l);
Cur_Position cur_First(Cur_List l);
Cur_Position cur_Advance(Cur_Position p);
Cur_Element cur_Retrieve(Cur_Position p);
void cur_Update(Cur_Position p,Cur_Element e);

#endif


实现文件 cur_list.c
/**********************************
*author:Felix
*last update:Tue Jan 1 04:33:03 EST 2008
*description:
*
*
*
*/
#include "cur_list.h"
struct Cur_Node
{
  Cur_Element e;
  Cur_Position next;
};
 
static struct Cur_Node CursorSpace[MAX_CURSOR_SIZE];
int CursorInitFlag=0;/*to decide whether it's been initialized*/
static Cur_Position CursorAlloc();
static void CursorFree(Cur_Position p);


/*assume that the first position is dump cursor(unused) that just for a sign*/
 Cur_Position CursorAlloc()
{
  Cur_Position p;
  p=CursorSpace[0].next;
  CursorSpace[0].next=CursorSpace[p].next;
  return p;
}
 void CursorFree(Cur_Position p)
{
 CursorSpace[p].next=CursorSpace[0].next;
 CursorSpace[0].next=p;
}
void cur_InitializeCursor()
{
  int i=0;
 if(CursorInitFlag==0)/*to decide whether it's been initialized*/
  {
  while(i<MAX_CURSOR_SIZE-1)
  CursorSpace[i].next=++i;
  CursorSpace[i].next=0;
  CursorInitFlag=1;
  }
}
Cur_List cur_MakeEmpty() {
  Cur_Position p;
  p= CursorAlloc();
  CursorSpace[p].next=0;
  return p;
}
int cur_IsEmpty(Cur_List l)
{
   return 0==CursorSpace[l].next;
}
int cur_IsLast(Cur_Position p)
{
   return 0==CursorSpace[p].next;
}
Cur_Position cur_Find(Cur_Element e,Cur_List l)
{
  Cur_Position p=cur_First(l);
  while(p&&CursorSpace[p].e!=e)p=cur_Advance(p);
  return p;
}
void cur_Delete(Cur_Element e,Cur_List l)
{
   Cur_Position p=cur_FindPrevious(e,l);
   Cur_Position tmp=cur_Advance(p);
   CursorSpace[p].next=cur_Advance(tmp);
   CursorFree(tmp);
}
Cur_Position cur_FindPrevious(Cur_Element e,Cur_List l)
{
 Cur_Position p=l;
  while(CursorSpace[p].next&&CursorSpace[CursorSpace[p].next].e!=e)p=cur_Advance(p);
  return CursorSpace[p].next?p:0;
}
Cur_Position cur_Insert(Cur_Element e,Cur_List l,Cur_Position p)
{
    Cur_Position tmp=(Cur_Position)CursorAlloc();
    if (!tmp) return 0;
    CursorSpace[tmp].e=e;
    CursorSpace[tmp].next=CursorSpace[p].next;
    CursorSpace[p].next=tmp;
   return tmp;
}
void cur_DeleteList(Cur_List l)
{
 CursorSpace[cur_Header(l)].next=0;
}
Cur_Position cur_Header(Cur_List l)
{
   return l;
}
Cur_Position cur_First(Cur_List l)
{
 return CursorSpace[l].next;
}

Cur_Position cur_Advance(Cur_Position p)
{
   return p?CursorSpace[p].next:0;
}
Cur_Element cur_Retrieve(Cur_Position p)
{
  return CursorSpace[p].e;
}
void cur_Update(Cur_Position p,Cur_Element e)
{
  CursorSpace[p].e=e;
}

/*****************
测试部分:
*************/
/*menu_c.h*/
/*///
*author:Felix
*create date:Tue Jan 1 05:13:11 EST 2008
*last update:Tue Jan 1 05:13:11 EST 2008
*description:
*
*
*/
#include <stdio.h>
#ifndef __MENU____
#define __MENU____
#define SELECT() ((___sel=___select())!='0')
#define SELECTION ___sel
char ___sel;
char ___select();
/*
 define the menu:
*/
#endif

/*menu_c.c*/
/*///
*author:Felix
*create date:Tue Jan 1 05:13:11 EST 2008
*last update:Tue Jan 1 05:13:11 EST 2008
*description:
*
*
*/
#include "menu_c.h"
char *___menu[]={
 
"1.Print list.h",
"2.Initialize the list with random integer.",
"3.Insert a number to the list.",
"4.Delete a number from the list.",
"5.Update a number in the list.",
"6.Delete the whole list.",
"7.Print the list",
"0.EXIT",
NULL
};
void ___showMenu()
{
 printf("please select:/n");
 char **p=___menu;
 while(*p)printf("%s/n",*p++);
 printf(":>");
}
char ___select()
{
char c;
 ___showMenu();
 while((c=getchar())=='/n');
 return c;
}



/*testList.c*/
/*///
*author:Felix
*create date:Tue Jan 1 05:13:11 EST 2008
*last update:Tue Jan 1 05:13:11 EST 2008
*description:
*
*
*//
#include "menu_c.h"
#include<stdio.h>
#include<stdlib.h>
#include<cur_list.h>
#define RAN_COUNT 30
#define DEF_MAX  9999
int main()
{
Cur_List l;
Cur_Position p;
int n,n2;
int count;
cur_InitializeCursor();
l=cur_MakeEmpty();

while(SELECT())
{
 switch (SELECTION)
 {
 /*Print list.h*/
 case '1':
    system("less ../cur_list.h");
    break;
 /*Initialize the list with random integer.*/
 case '2':
    count=RAN_COUNT;
    while(count-->0)cur_Insert(random_f(DEF_MAX),l,cur_Header(l));
    break;
 /*Insert a number to the list.*/
 case '3':
   printf("number to insert:>");
  if(scanf("%d",&n)>0)
   cur_Insert(n,l,cur_Header(l));
   else printf("illegal input");
    break;
 /*Delete a number from the list.*/
 case '4':
   printf("number to delete:>");
  if(scanf("%d",&n)>0)
   {
     if (cur_Find(n,l))cur_Delete(n,l);
     else printf("no match found/n");
   }else printf("illegal input/n ");
   break;
 /*Update a number in the list.*/
 case '5':
      printf("integer to update:>");   
  if(scanf("%d",&n)>0)
   {
     if (p=cur_Find(n,l))
     {
      printf("update with:>");   
      if(scanf("%d",&n2)>0)cur_Update(p,n2);
        else printf("illegal input");
     }
     else printf("no match found/n");
   }else printf("illegal input/n ");
  break;
 /*Delete the whole list.*/
 case '6':
  cur_DeleteList(l);
  break;
/*print the list*/
 case '7':
 p=cur_First(l);
 while(p)
  {
   printf("%d ",cur_Retrieve(p));
   p=cur_Advance(p);
  }
 default:break;
 }
}
return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值