線性錶鏈式存儲(單鏈表)

理解鏈式存儲

爲了表示數據元素與直接後繼數據元素的關係,每個數據元素除了保存自己的信息之外,還需要存儲直接後繼的信息。

那麼我們應該怎麼做呢?首先我們應該在每個數據結點中包含一個指針域(存儲直接後繼結點的頭部地址)。

 

                       

頭部結點:鏈表中的第一個結點,包含指向第一個數據元素的指針以及鏈表自身的一些信息

數據結點:鏈表中的數組元素結點,包含了下一個數據結點的指針和自身信息

尾結點:鏈表中最後一個數據元素結點,後繼結點爲空。

//LinkList.h
#pragma once
typedef void LinkList;

//數據元素結點
typedef struct tag_LinkListNode
{
    struct tag_LinkListNode *next;//指針域
}TLinkListNode;

//創建鏈表
LinkList *LinkList_Creat();
//銷燬鏈表
void LinkList_Destroy(LinkList*list);
//清空鏈表初始化鏈表
void LinkList_Clear(LinkList *list);
//獲取鏈表長度
int LinkList_GetLength(LinkList *list);
//插入結點
int LinkList_inster(LinkList *list, TLinkListNode *node, int pos);
//獲取指定位置結點
TLinkListNode *LinkList_Get(LinkList *list, int pos);
//刪除指定位置結點
TLinkListNode *LinkList_Delete(LinkList *list, int pos);

 

插入元素的操作

假設pos = 3表示在鏈表中下標爲3的位置插入一個節點。

提供一個輔助指針current,通過循環跳轉到pos-1的位置,current->next是current當前指向結點的後繼結點,那麼我們應該怎麼操作呢?

首先我們應該把Node結點的後繼指針指向current當前結點的後繼結點,其次current的後繼指針指向插入的結點,這樣就完成了鏈接。

node->next = current->next

curren->next = node

獲取指定元素的操作

這裏我們需要注意,指向頭部結點的指針移動n次和第n個元素之間的關係

假設我們要獲取pos = 3(索引下標)位置上的結點,那麼輔助指針current通過循環跳轉應該跳轉到pos-1的位置上,這樣我們要獲取的結點應該是current後繼指針指向的結點:current->next

刪除指定位置元素操作

刪除指定結點同樣要注意指向頭部結點的指針移動n次和第n個元素之間的關係

假設我們要刪除pos = 3位置上的結點,我們需要讓輔助指針current通過循環跳轉到pos-1的位置上

首先提供一個輔助指針結點用來存放要刪除的結點node,其次讓輔助指針current的後繼指針指向要刪除結點node的後繼結點。

node =  current->next;

current->next = node->next

//LinkList.c
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "LinkList.h"

//鏈式線性表
typedef struct tag_LinkList
{
    TLinkListNode header;//頭部結點
    int length;//線性表長度
}TLinkList;

//創建鏈式線性表
LinkList * LinkList_Creat()
{
    TLinkList *list = NULL;
    list = (TLinkList *)malloc(sizeof(TLinkList));//給鏈式線性表分配堆內存
    if (list == NULL)
    {
        printf("LinkList_Creat err: list = NULL");
        return NULL;
    }
    memset(list, 0, sizeof(TLinkList));//鏈式線性表初始化(分配了內存要負責)
    list->length = 0;
    list->header.next = NULL;
    return list;
}
//銷燬鏈式線性表
void LinkList_Destroy(LinkList * list)
{
    if (list == NULL)
    {
        printf("LinkList_Destroy err: list = NULL");
        return;
    }
    free(list);//直接釋放鏈式線性表堆內存
    printf("LinkList_Destroy finished \n");
    return;
}
//清空線性表
void LinkList_Clear(LinkList * list)
{
    TLinkList *temp = NULL;
    if (list == NULL)
    {
        printf("LinkList_Clear err: list = NULL");
        return;
    }
    temp = (TLinkList *)list;//類型轉換
    temp->length = 0;//重置長度
    temp->header.next = NULL;//頭結點置空
    return;
}
//獲取鏈表長度
int LinkList_GetLength(LinkList * list)
{
    TLinkList *temp = NULL;
    if (list == NULL)
    {
        printf("LinkList_GetLength err: list = NULL");
        return -1;
    }
    temp = (TLinkList *)list;//類型轉換
    return temp->length;//返回鏈表長度
}
//在指定位置插入結點
int LinkList_inster(LinkList * list, TLinkListNode * node, int pos)
{
    TLinkList *temp = NULL;
    int i = 0;
    if (list == NULL || node == NULL || pos < 0)
    {
        printf("LinkList_inster err: list = NULL || node = NULL || pos < 0");
        return -1;
    }
    temp = (TLinkList *)list;//類型轉換
    TLinkListNode * current = &(temp->header);//當前結點
    for (i = 0; i < pos && node->next != NULL; i++)//跳轉到插入位置的前一個結點位置處
    {
        current = current->next;
    }
    node->next = current->next;//插入節點的後繼指針指向當前結點的後繼結點
    current->next = node;//當前結點的後繼指針指向要插入的結點
    temp->length++;//鏈表長度+1
    return 0;
}
//獲取鏈表指定位置結點
TLinkListNode * LinkList_Get(LinkList * list, int pos)
{
    TLinkList *temp = NULL;
    int i = 0;
    if (list == NULL  || pos < 0)
    {
        printf("LinkList_Get err: list = NULL ||  pos < 0");
        return NULL;
    }
    temp = (TLinkList *)list;//類型轉換
    TLinkListNode * current = &(temp->header);//當前結點
    for (i = 0; i < pos ; i++)//循環跳轉到需要獲取結點的前一個結點處
    {
        current = current->next;
    }
    return current->next;//返回需要獲取的結點
}
//刪除鏈表指定位置結點
TLinkListNode * LinkList_Delete(LinkList * list, int pos)
{
    TLinkList *temp = NULL;
    int i = 0;
    if (list == NULL || pos < 0)
    {
        printf("LinkList_Get err: list = NULL ||  pos < 0");
        return NULL;
    }
    temp = (TLinkList *)list;//類型轉換
    TLinkListNode *current = &(temp->header);//輔助指針指向頭部結點
    TLinkListNode *ret = NULL;//輔助指針存放需要刪除的結點
    for (i = 0; i < pos; i++)//循環跳轉到要刪除幾點的前一個結點處
    {
        current = current->next;
    }
    ret = current->next;//臨時存放要刪除的結點
    current->next = ret->next;//當前結點的後繼指針指向要刪除結點的後繼節點處
    temp->length--;//鏈表長度-1
    return ret;//返回要刪除的結點
}
//測試代碼
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "LinkList.h"

typedef struct tag_Teacher
{
    TLinkListNode node;
    int age;
    char *name;
}Teacher;

int main(int argc, char** argv)
{
    Teacher t1, t2, t3, t4, t5;
    t1.age = 20;
    t1.name = "zhangsan";
    t2.age = 21;
    t2.name = "lisi";
    t3.age = 22;
    t3.name = "wangwu";
    t4.age = 23;
    t4.name = "zhaoliu";
    t5.age = 24;
    t5.name = "wangqi";

    LinkList *list = NULL;
    list = LinkList_Creat();
    if (list == NULL)
    {
        printf("LinkList_Creat err: list = NULL");
        return -1;
    }
    int i, ret = 0;
    //尾插法
    ret = LinkList_inster(list, (TLinkListNode *)&t1, LinkList_GetLength(list));
    ret = LinkList_inster(list, (TLinkListNode *)&t2, LinkList_GetLength(list));
    ret = LinkList_inster(list, (TLinkListNode *)&t3, LinkList_GetLength(list));
    ret = LinkList_inster(list, (TLinkListNode *)&t4, LinkList_GetLength(list));
    ret = LinkList_inster(list, (TLinkListNode *)&t5, LinkList_GetLength(list));

    printf("LinkList length = %d\n", LinkList_GetLength(list));

    for (i = 0; i < LinkList_GetLength(list); i++)
    {
        Teacher *t = (Teacher *) LinkList_Get(list, i);
        printf("age = %d,name = %s\n", t->age, t->name);
    }
    system("pause");
    return 0;
}

 

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