1. 程式人生 > >資料結構(c語言)——線性單鏈表基本操作

資料結構(c語言)——線性單鏈表基本操作

#include <stdio.h>
#include <stdlib.h>

typedef int Element;
typedef char(*Status)[10];

#define ERROR "error"
#define OK "ok";

// 定義一個線性單鏈表結構
typedef struct Node{
    Element data;
    struct Node *next;
}Node,*LinkedList;

// 初始化一個線性單鏈表
LinkedList init(){
    Node *l;
    l = (Node *)malloc(sizeof(Node));
    l->next = NULL;

    return l;
}

// 建立一個線性單鏈表
void create(LinkedList l){
    for(int i = 2; i < 5; i++){
        LinkedList p;
        p = (LinkedList)malloc(sizeof(Node));
        p->data = i;
        p->next = l->next;
        l->next = p;
    }
}

// 插入資料到線性單鏈表中(頭插法)
void insertHead(LinkedList l,Element e){
        LinkedList p;
        p = (LinkedList)malloc(sizeof(Node));
        p->data = e;
        p->next = l->next;
        l->next = p;
}

// 插入資料到線性單鏈表中(尾插法)
void insertTail(LinkedList L,Element e){
    LinkedList p,r;
    //r始終指向終端結點,開始時指向頭結點
    r = L;

    //就是將這個尾指標指向最後一個元素
    while(r->next){
        r = r->next;
    }
    //申請新的結點
    p = (LinkedList)malloc(sizeof(Node));
    p->data = e;

    // 將表尾終端節點的指標指向新節點
    r->next = p;

    // 將當前的新節點定義為表尾終端節點
    r = p;

    //表示當前連結串列結束
    r->next = NULL;
}

// 從線性單鏈表中取出指定位置的資料(位置從0開始)
Status LinkedListGet(LinkedList l,int i,Element *e){
    LinkedList p = l->next;
    int j = 0;
    while(p&&j<i){
        p = p->next;
        j++;
    }

    if(!p||j>i){
        return ERROR;
    }
    *e = p->data;
    return OK;
}

// 線性單鏈表的指定位置插入資料
Status LinkedListInsert(LinkedList L,int index,Element e){
    LinkedList pre,p;                      //pre為前驅結點
    pre = L->next;
    int tempi = 1;

    while(pre&&tempi<index){
        // 就是再尋找第i-1個節點

        pre = pre->next;
        ++tempi;
    }
    if(!pre||tempi>index){
        // 第index個節點不存在
        return ERROR;
    }
    p = (LinkedList)malloc(sizeof(Node));
    p->data = e;
    p->next = pre->next;
    pre->next = p;

    return OK;
}

// 刪除線性單鏈表的指定位置元素
Status LinkedListRemove(LinkedList L,int index,Element *e){

    LinkedList pre,p;
    //pre為頭指標

    pre = L->next;
    int tempi = 1;

    // 就是在尋找第i-1個節點
    while(pre&&tempi<index){

        pre = pre->next;
        ++tempi;
    }

    if(!(pre->next)||tempi>index){
        // 第index個節點不存在
        return ERROR;
    }
    p = pre->next;
    pre->next = p->next;
    *e = p->data;
    //將p的記憶體進行釋放
    free(p);

    return OK;
}

// 查詢線性單鏈表的指定元素,存在則返回這個元素的地址(不是所在的位置哦),不存在返回NULL;
Node * LinkedListIndexOf(LinkedList L,Element e){
    LinkedList p;
    if(!L){
        return ERROR;
    }
    p = L;
    while(p&&p->data!=e){
        p = p->next;
    }
    return p;
}

// 清空線性表
Status LinkedListClear(LinkedList L){
    LinkedList p,q;
    p = L->next;
    while(p){
        q = p->next;
        free(p);
        p = q;
    }
    // 將頭節點的指標域置為空。
    L->next = NULL;
    return OK;
}


// 打印出線性單鏈表的所有資料元素
void toString(LinkedList l){
    printf("[");
    l = l->next;
    while(l){
        printf("%d",l->data);
        l=l->next;
        if(l){
            printf(",");
        }
    }
    printf("]\n");
}

int main(){
    LinkedList L = init();

    create(L);

    //insertHead(L,5);
    insertTail(L,1);

    Element a = -1;
    // Element *a = &1;不要幹這麼傻逼的事情,常數的地址賦值給指標變數沒有任何意義,c語言不允許這麼做。
    // Element *a = 1;表示*a所儲存的地址值為1。
    // 指標是用來存放地址的!地址就是個常數!雖然這樣是能編譯通過的!(準確地說,只能賦值0,其他的都不合法)。
    // 但是,這樣執行會出錯(段錯誤)的!因為指標本來是存放地址的,而你卻存放了一個常數(即一個不合法的地址),
    // 這樣就會使指標指向不確定的記憶體單元(非法訪問),從而出現錯誤!

    Element *intPoint=&a;
    // *intPoint=a;等同於:int *intPoint; *intPoint = a;
    // 這個指標都沒指向任何地址,也就不存在值,取也就會出錯

    // 取出連結串列中第0個數據元素(下標從0開始)
    Status res = LinkedListGet(L,0,intPoint);

    printf("Get() res is :%s,element is %d\n",res,*intPoint);

    LinkedListInsert(L,2,5);

    res = LinkedListRemove(L,3,intPoint);
    printf("remove status :%s,remove Element is %d\n",res,*intPoint);

    Node *indexRes = LinkedListIndexOf(L,7);
    printf("..index Memory address :%d\n",indexRes);

//LinkedListClear(L);

    toString(L);

    return 0;
}

不足和錯誤之處還請多多指正,謝謝!