静态链表的C实现和核心点(基于数据结构 严蔚敏)

静态链表是利用一维数组实现逻辑上的单链表结构,结点的逻辑上相邻但物理位置上不一定相邻,因为内存分配上是一次性的,故称为静态。

特点:

  • 预先需要一片连续的存储空间;
  • 非随机存取;
  • 无现成的“内存”分配和回收函数,得自己实现;
  • 最多存储MAXSIZE - 1个数据;

核心包含了两个链表:

  • 数据链表(初始化完成后需记住头结点,一般为数组的第1个分量)
  • 备用的空闲链表(数组的第0个分量是备用链表的头结点)
  • 注意逻辑位序和物理位序,实际上并没有利用物理位序的使用操作,牢牢记住它只是一个单链表

这两个链表都需要自己维护。

核心函数 :

  • "内存"申请函数 int Malloc_SL();该函数返回申请的结点下标。
  • "内存"释放函数void Free_SL(int k);释放逻辑位序k。

注意函数:

  • void InitSpace_SL();该函数初始化链表空间,不做其他操作;
  • int InitList_SL(SLinkList *h);该函数初始化数据链表并返回数据链表的头结点,这个头结点h非常重要,书本上没有这个函数的介绍,导致有些人搞不懂对数据链表的操作该如何进;

Status.h文件

#ifndef STSTUS_H
#define STSTUS_H

#define TRUE    1    //
#define FALSE    0    //

#define YES    1    //
#define NO    0    //

#define OK    1    //通过
#define ERROR    0    //错误

#define SUCCESS    1    //成功
#define UNSUCCESS    0    //失败
#define INFEASIBLE    -1    //不可行

#define OVERFLOW    -2    //堆栈上溢
#define UNDERFLOW    -3    //堆栈下溢

typedef int Status;

#define PressEnter \
{\
fflush(stdin);\
printf("Press Enter...");\
getchar();\
fflush(stdin);\
}

#endif

StaticLinkedList.h文件

 1 #ifndef STATICLINKEDLIST_H_
 2 #define STATICLINKEDLIST_H_
 3 
 4 #include "Status.h"
 5 
 6 #define MAXSIZE 30
 7 typedef int ElementType;
 8 typedef int SLinkList;
 9 
10 typedef struct
11 {
12     ElementType data;
13     int cur;
14 }Component[MAXSIZE];
15 
16 
17 
18 //初始化,将一维数组Space中各分量链成一个大的备用空间
19 void InitSpace_SL();
20 
21 //为插入的输入申请空间,从备用空间取得一个结点,返回分配结点下标
22 int Malloc_SL();
23 
24 //将下标为k的空闲结点回收
25 void Free_SL(int k);
26 
27 //初始化静态链表,建立头结点,返回头结点下标
28 int InitList_SL(SLinkList *h);
29 
30 //置空
31 Status ClearList_SL(SLinkList h);
32 
33 //销毁
34 void DestroyList_SL(SLinkList* h);
35 
36 //判空
37 Status ListEmpty_SL(SLinkList h);
38 
39 //求长
40 int ListLength_SL(SLinkList h);
41 
42 //取值
43 //h--头结点,i--逻辑位置(1->maxsize-2),e--返回值
44 Status GetElem_SL(SLinkList h, int i, ElementType* e);
45 
46 //返回元素e的位序
47 int LocateElem_SL(SLinkList h, ElementType e);
48 
49 //前驱
50 //找值为cur_e的结点的前一个结点的值
51 Status PriorElem_SL(SLinkList h, ElementType cur_e, ElementType* pre_e);
52 
53 //后继
54 Status NextElem_SL(SLinkList h, ElementType cur_e, ElementType* next_e);
55 
56 //插入
57 //在逻辑上第i个位置前插入数据,使其成为第i个位置
58 //i从1开始
59 Status ListInsert_SL(SLinkList h, int i, ElementType e);
60 
61 //删除
62 Status ListDelete_SL(SLinkList h, int i, ElementType* e);
63 
64 //遍历
65 Status ListTraverse_SL(SLinkList h, void(Visit)(ElementType));
66 
67 #endif

StaticLinkedList.cpp文件

  1 #include "stdafx.h"
  2 #include <cstdlib>
  3 
  4 #include "StaticLinkedList.h"
  5 
  6 //定义静态链表空间
  7 Component Space;
  8 
  9 void InitSpace_SL()
 10 {    //初始化备用空间,形成备用链表
 11     
 12     for (size_t i = 0; i < MAXSIZE - 1; ++i)    //将0号单元做备用空间的起始结点
 13     {
 14         Space[i].cur = i + 1;    //各空间结点逻辑上首尾相连
 15     }
 16     Space[MAXSIZE - 1].cur = 0; //最后一个结点下标指向NULL = 0,相当于链表的尾指针
 17 }
 18 
 19 int Malloc_SL()
 20 {
 21     int i = Space[0].cur;
 22 
 23     if (Space[0].cur)
 24     {
 25         //将申请到的空间从备用链表空间中断开,并为下一个空闲结点做准备,即将下一个空闲结点链接到s[0]下
 26         Space[0].cur = Space[i].cur;
 27         return i;                     //返回申请到的空间下标
 28     }
 29     return 0;    //申请失败返回0
 30 }
 31 
 32 void Free_SL(int k)
 33 {
 34     Space[k].cur = Space[0].cur;    //将k结点的下个结点置为备用链表的第一个结点
 35     Space[0].cur = k;    //将K结点置为备用空间的第一个结点
 36 }
 37 
 38 int InitList_SL(SLinkList * h)
 39 {
 40     *h = Malloc_SL();    //创建头结点
 41     if (!(*h))
 42     {
 43         exit(OVERFLOW);    //空间已满
 44     }
 45 
 46     Space[*h].cur = 0;    //头结点游标置为0
 47     return OK;
 48 }
 49 
 50 Status ClearList_SL(SLinkList h)
 51 {
 52     int p;
 53     if (!h)
 54     {
 55         return ERROR;
 56     }
 57     p = Space[h].cur; //p指向第一个结点
 58     while (p)
 59     {
 60         Space[h].cur = Space[p].cur; //从数据链表首结点开始删除
 61         Free_SL(p);
 62         p = Space[h].cur;
 63     }
 64 
 65     return OK;
 66 }
 67 
 68 void DestroyList_SL(SLinkList * h)
 69 {
 70     ClearList_SL(*h);
 71     Free_SL(*h);    //释放头结点
 72     *h = 0;
 73 }
 74 
 75 Status ListEmpty_SL(SLinkList h)
 76 {
 77     if (h && !Space[h].cur)
 78     {
 79         return TRUE;
 80     }
 81     return FALSE;
 82 }
 83 
 84 int ListLength_SL(SLinkList h)
 85 {
 86     if (!h)
 87     {
 88         exit(OVERFLOW);
 89     }
 90 
 91     int count, p;
 92     count = 0;
 93     p = Space[h].cur;
 94     while (p)
 95     {
 96         count++;
 97         p = Space[p].cur;
 98     }
 99     return count;
100 }
101 
102 Status GetElem_SL(SLinkList h, int i, ElementType * e)
103 {
104     //-2 去掉备用头结点和数组溢出两个
105     if (!h || i < 1 || i > MAXSIZE - 2) 
106     {
107         return ERROR;
108     }
109 
110     int count, p;
111     count = 0;
112     p = Space[h].cur;
113     while (p)
114     {
115         count++; //先++,从第一个逻辑位置开始,count很重要,寻找操作都需要count计数
116         if (count == i)
117         {
118             *e = Space[p].data;
119             return OK;
120         }
121         p = Space[p].cur;
122     }
123     return ERROR;
124 }
125 
126 int LocateElem_SL(SLinkList h, ElementType e)
127 {
128     int k, count;
129     count = 1;
130     if (h && Space[h].cur) //不为空表
131     {
132         k = Space[h].cur;
133         while (k && Space[k].data != e)
134         {
135             count++;
136             k = Space[k].cur;
137         }
138         if (k)
139         {
140             return count;
141         }
142     }
143     return 0;
144 }
145 
146 Status PriorElem_SL(SLinkList h, ElementType cur_e, ElementType * pre_e)
147 {
148     int p, q;
149     if (h)
150     {
151         p = Space[h].cur;
152         if (p && Space[p].data != cur_e)
153         {
154             q = Space[p].cur;
155             while (q && Space[q].data != cur_e)
156             {
157                 p = q;        //用p记住前驱
158                 q = Space[q].cur;
159             }
160             if (q)
161             {
162                 *pre_e = Space[q].data;
163                 return OK;
164             }
165         }
166     }
167     return ERROR;
168 }
169 
170 Status NextElem_SL(SLinkList h, ElementType cur_e, ElementType * next_e)
171 {
172     int p;
173     if (h)
174     {
175         p = Space[h].cur;
176         if (p && Space[p].data != cur_e)
177         {
178             p = Space[p].cur;
179 
180             if (p && Space[p].cur)
181             {
182                 p = Space[p].cur;
183                 *next_e = Space[p].data;
184                 return OK;
185             }
186         }
187     }
188     return ERROR;
189 }
190 
191 Status ListInsert_SL(SLinkList h, int i, ElementType e)
192 {
193     if (!h)
194     {
195         return ERROR;
196     }
197 
198     int count, k, p;
199     if (i > 0) //
200     {
201         count = 0;
202         k = h;
203 
204         while (k && count < i - 1) //找到逻辑插入位置的前一个位置
205         {
206             count++;
207             k = Space[k].cur;
208         }
209         if (k)    //找到第i-1个元素位置
210         {
211             p = Malloc_SL();
212             if (!p)
213             {
214                 return ERROR;
215             }
216             Space[p].data = e;
217             Space[p].cur = Space[k].cur;
218             Space[k].cur = p;
219 
220             return OK;
221         }
222     }
223     return ERROR;
224 }
225 
226 Status ListDelete_SL(SLinkList h, int i, ElementType * e)
227 {
228     if (!h)
229     {
230         return ERROR;
231     }
232     
233     int count, k, p;
234     if (i > 0)
235     {
236         count = 0;
237         k = h;
238         while (k && count < i -1) //找到删除位置的前一个位置
239         {
240             count++;
241             k = Space[k].cur;
242         }
243 
244         if (k && Space[k].cur)  //找到第i-1个元素却不是尾结点
245         {
246             p = Space[k].cur;    //p指向第i结点
247             *e = Space[p].data;
248             Space[k].cur = Space[p].cur;
249             Free_SL(p);
250 
251             return OK;
252         }
253     }
254     return ERROR;
255 }
256 
257 Status ListTraverse_SL(SLinkList h, void(Visit)(ElementType))
258 {
259     if (!h)
260     {
261         return ERROR;
262     }
263     
264     int p = Space[h].cur;
265     while (p)
266     {
267         Visit(Space[p].data);
268         p = Space[p].cur;
269     }
270 
271     return OK;
272 }

Main函数

void PrintElem(ElementType e)
{
    printf("%d ", e);
}

int main()
{
    SLinkList h; //数据链表头结点,全局
    ElementType e;
    int i;

    printf("初始化静态链表的备用空间Space....");
    InitSpace_SL();
    printf("\n");
    PressEnter;

    printf("初始化静态链表头结点H,申请空间....");
    InitList_SL(&h);
    printf("\n");
    PressEnter;

    ListEmpty_SL(h) ? printf("h为空!\n") : printf("h不为空!\n");
    printf("\n");
    PressEnter;

    for (size_t j = 1; j < 6; ++j)
    {
        printf("在h第%d个位置插入%d\n", j, 2 * j);
        ListInsert_SL(h, j, 2 * j);
        printf("\n");
    }
    printf("h中的元素为:h=");
    ListTraverse_SL(h, PrintElem);
    printf("\n");
    PressEnter;

    printf("h的长度为%d\n", ListLength_SL(h));
    printf("\n");
    PressEnter;

    ListDelete_SL(h, 4, &e);
    printf("删除h中第 4 个元素 %d,用Free_SL释放空间....", e);
    printf("\n");
    PressEnter;

    printf("删除后h中的元素为:h=");
    ListTraverse_SL(h, PrintElem);
    printf("\n");
    PressEnter;

    printf("元素8在h中的位序为%d\n",LocateElem_SL(h,8));
    printf("\n");

    printf("清空h前:");
    ListEmpty_SL(h) ? printf("h为空!\n") : printf("h不为空!\n");
    ClearList_SL(h);
    printf("清空h后:");
    ListEmpty_SL(h) ? printf("h为空!\n") : printf("h不为空!\n");
    printf("\n");
    PressEnter;

    printf("销毁h前:");
    h ? printf("h存在!\n") : printf("h不存在!\n");
    DestroyList_SL(&h);
    printf("销毁h后:");
    h ? printf("h存在!\n") : printf("h不存在!\n");
    printf("\n");
    PressEnter;
return 0; }

 

posted @ 2018-04-07 21:58  香蕉有毒  阅读(1711)  评论(0编辑  收藏  举报