靜態鏈表的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; }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM