C語言數據結構和算法,第一節-----C語言實現線性表

線性表(線性存儲):

其實 線性表理解數據是連續的,意思就是中間不能間隔,不能跳躍式的存儲。

實現方式,一種是線性存儲,一種是鏈式存儲。其實理解線性表其實主要問題在於如何將業務結點存進線性表

1.線性存儲,我們是通過數組來實現的:

譬如我們有一個業務結構,譬如person的結構體:

typedef struct person
{
    int age;
    char name[64];
}person;

     ,那麼我們如何將一個一個的person的結點存進線性表呢,我們可以通過void * 可以接收任何指針類型的方式來實現,這樣我們的線性存儲可以這樣定義:

typedef struct _seqlist
{
    int length,
    int capacity',
    void **ptr,
}seqlist;

   而線性表的結點,我們可以這樣定義,因爲void * 類型可以接收任意的指針類型

typedef void * seqlistnode;

一、線性表線性存儲的API函數:

1.先創建一個線性表:

//創建一個線性表
seqlist*seqlist_create(int cap)
{
    int ret = 0;
    if(cap <0)
    {
        ret = -1;
        printf("seqlist_create error ,傳進來的容量小於了0:%d \n",ret);
        return NULL;
    }

    seqlist *tmp = NULL;
    tmp = malloc(sizeof(seqlist));
    if(NULL == tmp)
    {
        ret = -2;
        printf("seqlist_create error ,申請內存失敗:%d \n",ret);
        return NULL;
    }

    tmp->length = 0;
    tmp->capacity = cap;
    tmp->ptr = malloc(sizeof(void *) *cap);
    if(NULL ==tmp->ptr)
    {
        ret = -3;
        printf("seqlist_create error ,申請內存失敗:%d \n",ret);
        return NULL;
    }
    return tmp;
}

2.獲取線性表的長度

int seqlist_length(seqlist *seq)
{
    int ret = 0;
    if(NULL == seq)
    {
        ret = -1;
        printf("seqlist_length error ,傳進的參數是無效的:%d \n",ret);
        return ret;
    }

    return seq->length;
}

3.獲取線性表容量

int seqlist_capacity(seqlist *seq)
{
    int ret = 0;
    if(NULL == seq)
    {
        ret = -1;
        printf("seqlist_capacity error ,傳進的參數是無效的:%d \n",ret);
        return ret;
    }

    return seq->capacity;
}

4.銷燬線性表

void seqlist_dsetroy(seqlist* seq)
{
    int ret = 0;
    if(NULL == seq)
    {
        ret = -1;
        printf("seqlist_setroy error ,傳進的參數是無效的:%d \n",ret);
        return ;
    }

    if( NULL != seq->ptr)
    {
        free(seq->ptr);
    }

    free(seq);
    return ;
}

5。清空線性表

void seqlist_clear(seqlist *seq)
{
    int ret = 0;
    if(NULL == seq)
    {
        ret = -1;
        printf("seqlist_setroy error ,傳進的參數是無效的:%d \n",ret);
        return ;
    }

    seq->length = 0;
    return ;
}

6.往線性表插入一個結點


int seqlist_insert(seqlist *seq,seqlistnode * node,int pos)
{
    int ret = 0;

    if(NULL ==seq || pos <0||NULL == node)
    {
        ret = -1;
        printf("seqlist_insert error ,傳入的參數都是無效的:%d \n",ret);
        return -1;
    }

    if(seq->length >= seq->capacity)
    {
        ret = -2;
        printf("seqlist_insert 線性表已經滿了:%d \n",ret);
        return -2;
    }

    if(pos > seq->length-1)
    {
        pos = seq->length;
    }

    //往線性表插入數據,那麼將pos位置的數據往後移一位,這樣就可以將pos位置的數據空出來存放node,、
    //這樣操作不管你是長度爲0,並且想頭插,或者你想尾插,或者中間插入都是可以滿足的
    for(int i = seq->length -1; i>=pos;i--)
    {
        seq->ptr[i+1] = seq->ptr[i];
    }

    seq->ptr[pos] = node;
    seq->length++;
    return ret;


}

7.從線性表內部刪除一個結點

int seqlist_delete(seqlist *seq,int pos)
{
    int ret = 0;
    if(NULL == seq|| pos < 0)
    {
        ret = -1;
        printf("seqlist_delete error,傳入的參數不對:%d \n",ret);
        return ret;
    }

    if(seq->length == 0)
    {
        ret = -2;
        printf("seqlist_delete error,線性表長度爲0:%d \n",ret);
        return ret;
    }


    for(int i = pos;i <= seq->length-2;i++)
    {
        seq->ptr[i] = seq->ptr[i+1];
    }

    seq->length--;

    return ret;

}

 

這幾個API函數可以卸載一個seqlist.c的源文件裏面

二、seqlist.h的頭文件可以寫爲:

#ifndef __SEQLIST__
#define __SEQLIST__


typedef void  seqlistnode;
typedef struct _seqlist
{
    int capacity;
    int length;
    void **ptr;
}seqlist;
seqlist*seqlist_create(int cap);
int seqlist_length(seqlist *seq);
int seqlist_capacity(seqlist *seq);
void seqlist_dsetroy(seqlist* seq);
void seqlist_clear(seqlist *seq);
int seqlist_insert(seqlist *seq,seqlistnode * node,int pos);
int seqlist_delete(seqlist *seq,int pos);

#endif

三、測試的代碼爲main.c

#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include"seqlist.h"
typedef struct person
{
    int age;
    char name[64];
}person;
int main(int argc,char* argv[])
{
    seqlist *seq = seqlist_create(10);

    person p1;
    person p2;
    person p3;
    person p4;
    person p5;
    p1.age = 10;
    p2.age = 11;
    p3.age = 12;
    p4.age = 13;
    p5.age = 14;

    seqlist_insert(seq,(seqlistnode *)&p1,0);
    seqlist_insert(seq,(seqlistnode *)&p2,0);
    printf("線性表目前長度爲:%d \n",seqlist_length(seq));
    seqlist_insert(seq,(seqlistnode *)&p3,0);
    seqlist_insert(seq,(seqlistnode *)&p4,0);
    printf("線性表目前長度爲:%d \n",seqlist_length(seq));
    seqlist_insert(seq,(seqlistnode *)&p5,0);
    printf("線性表目前長度爲:%d \n",seqlist_length(seq));
 
    for(int i = 0; i < seq->length;i++)
    {
        printf("年齡爲:%d \n",((person *)(seq->ptr[i]))->age);
    }

    for(int i = 0; i < 5;i++)
    {
        seqlist_delete(seq,0);
    }
    printf("線性表目前長度爲:%d \n",seqlist_length(seq));
    return 0;
}

四、三個源文件編譯成可執行程序的makefile:

main:seqlist.o main.o
	gcc seqlist.o main.o -o main

%o:%c
	gcc -c $^ -o $@


clean:
	rm -rf *.o 
	rm -rf main

這樣,整個線性表的線性存儲的代碼就寫完了。

刪除節點和插入節點的關鍵在於理解數組元素的移動,插入元素,需要將pos位置所有元素往後移動一個,刪除將往前移動即可。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章