1. 程式人生 > 實用技巧 >靜態連結串列 - C語言

靜態連結串列 - C語言

#include <stdlib.h>
#include <stdio.h>
#define STATUS_OK 0
#define STATUS_FAILED -1
// 定義基本資料結構
// 1 利用大陣列定義靜態連結串列,陣列由頭結點,尾結點,已用連結串列,備用連結串列四部分構成
// 2 陣列頭結點:存放連結串列第一個結點的索引值
// 3 陣列尾結點:存放備用連結串列第一個結點的索引值
#define MAXSIZE 10
typedef char ElemType;
typedef struct node {
    ElemType data;
    int cur;
}LNode;                                                                    // 定義結點名稱
typedef LNode StaticLinkedList[MAXSIZE]; // 定義連結串列名稱
// 常見操作:
// init - 核心
// insert - 核心
// delete - 核心
// find
// traverse
// length
// 初始化操作:本質是將一個大陣列賦索引值,形成空的單鏈表的過程
// 賦值過程分為:
//     a. 頭結點:備用連結串列的頭結點索引位置,賦值為0,尾結點:連結串列的第一個結點的索引,賦值為0
//     b. 普通結點:指向陣列下個元素的索引位置,索引值+1
void init(StaticLinkedList list) {
    for (int i = 0; i < MAXSIZE - 1; i++) {
        list[i].cur = i + 1; // 各個結點的指標指向下一陣列序號
    }
    list[MAXSIZE - 1].cur = 0;
}
// 申請記憶體空間操作:
// 1 本質是將備用連結串列第一個結點取出,並更新備用連結串列第一個結點的指向
int malloc_node(StaticLinkedList list)
{
    int p = list[0].cur;                                   // 備用連結串列第一個結點的索引
    printf("malloc_node-1-p索引值:%d\n", p);
    if (list[0].cur) {                                            // 是否非0,初始化以後,除了陣列最後一個結點,都是非零。排除陣列尾結點
        list[0].cur = list[p].cur;                      // 更新備用連結串列頭結點索引
    }
    return p;
}
// 釋放操作:
// 1 本質是將結點新增到備用連結串列的過程
void free_node(StaticLinkedList list, int k)    // 結點釋放後,放到備用連結串列的第一個結點位置。頭插法
{
    printf("free_node-1-p索引值:%d\n", list[0].cur);
    list[k].cur = list[0].cur;                             // 原第一結點的指向賦給k結點的指向
    list[0].cur = k;                                              // 更新第一結點指向為索引值k
    printf("free_node-2-p索引值:%d\n", list[0].cur);
}
// 插入操作:在初始化形成的空靜態連結串列基礎上進行插入
// 步驟:
// 1 從備用連結串列中拿出一個結點---->自定義malloc函式
// 2 將拿出的結點賦值後,連結到連結串列指定位置
int insert(StaticLinkedList list, int k, ElemType x)
{
    if (k < 1 || k > length(list) + 1) return;
    int p = MAXSIZE - 1;
    int j = malloc_node(list);
    if (j) {                                                             // 排除陣列尾結點
        list[j].data = x;
        for (int i = 1; i < k; i++) {                   // for迴圈執行1次,p指向第1個元素的索引
            p = list[p].cur;
        }
        list[j].cur = list[p].cur;
        list[p].cur = j;
        return STATUS_OK;
    }
    return STATUS_FAILED;
}
// 刪除結點:
// 1 找到該結點前一結點k-1, 將k+1結點的索引賦給k-1的向量
// 2 釋放k結點
void delete_node(StaticLinkedList list, int k)
{
    if (k < 1 || k > length(list)) return;
    int p = MAXSIZE - 1;
    for (int i = 1; i < k; i++) {
        p = list[p].cur;
    }                                                                          // for迴圈結束後,p為k-1結點的index值
    int q = list[p].cur;                                   // q 為第k個結點
    list[p].cur = list[q].cur;                             // k+1 指向賦給 k-1
    free_node(list, q);
}
// 遍歷連結串列
// 1 從第一個結點【陣列尾結點所指向的結點】開始,依次遍歷每個結點的數值
void traverse(StaticLinkedList list)
{
    int p = list[MAXSIZE - 1].cur;                                       // 連結串列第一個結點的索引
    while (p > 0)
    {
        printf("索引值:%d, 指標向量值:%d, 資料值:%c\n", p, list[p].cur, list[p].data);
        p = list[p].cur;
    }
}
int length(StaticLinkedList list)
{
    int j = 0;
    int p = list[MAXSIZE - 1].cur;                                       // 連結串列第一個結點的索引
    while (p > 0)
    {
        p = list[p].cur;
        j++;
    }
    return j;
}
void traverseArray(StaticLinkedList list) {
    for (int i = 1; i < MAXSIZE; i++) {
        printf("索引值:%d, 指標向量值:%d, 資料值: %c\n", i, list[i].cur, list[i].data);
    }
}
int main()
{
    StaticLinkedList list;
    int status;
    init(list);

    printf("Init finished, static link list length:%d \n", length(list));
    insert(list, 1, 'A');
    insert(list, 2, 'B');
    insert(list, 3, 'C');
    insert(list, 4, 'D');
    insert(list, 5, 'E');
    insert(list, 6, 'F');
    insert(list, 7, 'G');/*
    insert(list, 8, 'H');
    insert(list, 9, 'I');
    insert(list, 10, 'K');
    insert(list, 11, 'G');*/
    traverseArray(list);
    /*printf("=========================分割線=========================\n");
    insert(list, 4, 'N');
    traverse(list);
    traverseArray(list);*/
    printf("=========================分割線=========================\n");
    delete_node(list, 2);
    traverseArray(list);
    printf("=========================分割線=========================\n");
    traverse(list);
}