數據結構簡單話(一)線性表

前言

本菜鳥筆者打算入門一下數據結構,在學習過程中通過自己簡單話術總結相關基礎知識要點,希望能幫助同樣在入門的小夥伴們快速了解相關基礎知識的輪廓,然後根據知識點再進一步的學習和理解。整個系列採用c語言來實現,程式碼會提供注釋,方便理解實現思路。

邏輯結構

線性表是0個或多個的有窮序列,\(k_0\)\(k_1\)的前驅,\(k_1\)\(k_0\)的後繼,除了首尾結點以外每個結點元素都有且只有一個前驅和一個後繼(類似於現實生活中排隊)。

物理存儲結構

一、順序表

  1. 概念:採用一組相鄰且連續的存儲空間存儲元素。即:存儲一個元素需要2個單位地址空間,從1號開始存儲,則第二個元素存儲首地址為3號,以此類推。程式碼實現中常用數組作為順序表元素的存儲。

  2. 優缺點

    1. 優點:方便查找,確定首地址就可以查找任意下標的元素。由此可以隨機存取。
    2. 缺點:不易於插入刪除,由於順序表中元素地址是相鄰的,當插入或者刪除一個元素後,修改位置之後的所有元素都需要移動,空間開銷大(類比排隊中一個人出或者插入到隊伍中,後面的所有人都需要向前或向後移動)
  3. 程式碼實現(初始化增刪改查)

    #include<stdlib.h>
    #include<stdio.h>
    
    #define MAXMIUM 100 //定義數組容量最大值
    /*結構體*/
    typedef struct SeqList
    {
        int element[MAXMIUM];//存放整型數據的數組
        int n;//數組元素個數
    }SeqList;
    /*初始化,創建一個順序表*/
    SeqList *createNullSeq()
    {
        SeqList *list = (SeqList *)malloc(sizeof(SeqList));
        if (list == NULL)
        {
            printf("wrong");
        }
        else
        {
            list->n = 0;//初始化的數組內沒有元素,所以n=0
        }
        return list;
    }
    
    /*在指定下標位置插入元素*/
    int insert(SeqList* list , int data,int index){
        if(list->n < MAXMIUM && index<=list->n){//插入前數組個數不能達到上限,下標需要在有效範圍內
            int i;
            for(i=list->n-1;i>=index;i--){//當前插入元素的位置和位置後的元素都需要往後移動一位
                list->element[i+1] = list->element[i];
            }
            i++;
            list->element[i] = data;
            list->n++;
            return 1;
        }
        return 0;
        
    }
    /*刪除指定位置的元素*/
    int delete(SeqList* list,int index){
        if(index<=list->n-1&&index>=0){//跟插入類似,判斷有效條件
            for(int i=index;i<list->n-1;i++){//刪除的位置以及後面的元素都需要往前移動一格
                list->element[i] = list->element[i+1];
            }
            list->n--;
            return 1;
        }
        return 0;
    }
    /*簡單線性表判空*/
    int isNull(SeqList* list){
        return list->n==0?1:0;
    }
    /*查找元素*/
    int locate_seq(SeqList* list,int data){
        if(list->n==0){
            return -1;
        }
        for(int i=0;i<list->n;i++){
            if(list->element[i]==data){
                return i;
            }
        }
        return -1;
    }
    /*獲得指定下標的元素*/
    int find(SeqList* list,int x){
        if(x>=0||x<list->n){
            return list->element[x];
        }
    
        return -1;
    }
    
    

二、鏈表

  1. 原理

    順序表插入刪除需要大量空間損耗(因為需要移動),所以可以採用鏈表的方式減少損耗。每個結點元素在存儲元素資訊時(數據域),還需要額外存儲一個指針域,用於存儲指向下一個結點的地址。這樣相鄰結點之間的地址無需相鄰。插入刪除時只需要修改相關指針域即可。

  2. 優缺點

    1. 優點:插入刪除空間代價小,只需要直接修改指針域。
    2. 缺點:查找麻煩,每次查找都需要從頭結點遍歷。
  3. 程式碼實現(初始化增刪改查)

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct PNode
    {
        struct PNode *next;
        int data;
    } PNode;
    
    PNode *createNullNode()
    {
        PNode *node = (PNode *)malloc(sizeof(PNode));
        if (node == NULL)
        {
            printf("wrong");
            return NULL;
        }
        node->next = NULL;
        node->data = 0;
        return node;
    }
    
    /*帶頭結點插入*/
    int insertNode(PNode *list, int i, int data)
    {
        if (list == NULL)
        {
            printf("null");
            return 0;
        }
        int p = 0;
        while (list->next != NULL)
        {
            if (p != i)
            {
                list = list->next;
                p++;
            }else{
              break;  
            }
        }   
        if (p == i)
        {
            PNode *temp = list->next;
            PNode *node = createNullNode();
            node->next = temp;
            node->data = data;
            list->next = node;
            return 1;
        }
        printf("out of range");
        return 0;
    }
    /*帶頭結點刪除第一個值為x的結點*/
    int delete(PNode *list,int x){
        if(list==NULL){
            printf("list is null");
            return 0;
        }
        while(list->next!=NULL&&list->next->data!=x){
            list = list->next;
        }
        if(list->next!=NULL&&list->next->data==x){
            PNode* temp = list->next;
            list->next = temp->next;
            temp->next = NULL;
            free(temp);
            return 1;
        }
        printf("no found %d",x);
        return 0;
    }
    
    /*通過下標查找元素,帶頭結點*/
    PNode *find(PNode* list,int i){
        if(list==NULL){
            printf("null list ");
            return NULL;
        }
        int cursor = 0;
        while(list->next!=NULL&&cursor!=i){
            list = list->next;
            cursor++;
        }
        if(cursor==i){
            printf("find %d",list->next->data);
            return list->next;
        }
        printf("out of range");
        return NULL;
    }
    
    /*判空*/
    int isNull(PNode* list){
        return list==NULL?1:list->next==NULL?1:0;
    }
    int main()
    {
        PNode *head = createNullNode();
        int flag = isNull(head);
        printf("%d\n",isNull(head));
        insertNode(head,0,1);
        insertNode(head,1,2);
        insertNode(head,2,3);
        insertNode(head,3,4);
        insertNode(head,2,77);
        // find(head,2);
        printf("%d",isNull(head));
    }
    

總結

  1. 鏈表方便增刪,順序表方便查找
  2. 鏈表的增刪主要通過修改指針,順序表增刪主要通過移動元素。
  3. 歡迎前往我的個人空間 菜鳥小白的個人空間 查看其他技術內容,留下友好評論和點贊,共同進步。