数据结构与算法基础-学习-04-线性表之链式表-查找元素返回位置、查找元素返回指针、插入元素等实现

一、测试环境

名称
cpu12th Gen Intel® Core™ i7-12700H
操作系统CentOS Linux release 7.9.2009 (Core)
内存3G
逻辑核数2
gcc 版本4.8.5 20150623

二、函数介绍

线性表之链式表的相关函数包括之前篇章《数据结构与算法基础-学习-03-线性表之链式表-初始化、销毁、清理、获取长度、判断为空、获取元素等实现》写的,都以此最新的篇幅为准。

1、CopyElemTypeData

(1)用途

将结构体Src中的数据复制到结构体Dest中。

(2)函数定义
Status CopyElemTypeData(ElemType *Dest, ElemType *Src)
{
    printf("Copy Elem Type Data\n");
    strcpy(Dest->StudentNum,Src->StudentNum);
    strcpy(Dest->StudentName,Src->StudentName);
    Dest->StudentScore = Src->StudentScore;
    Dest->NextPointer  = Src->NextPointer;
    PrintPretty();
    return SuccessFlag;
}
(3)参数说明
参数名说明
Dest目的端结构体。
Src源端结构体。

2、CmpElemType

(1)用途

比较两个结构体E1、E2是否相等。

(2)函数定义
Status CmpElemType(ElemType *E1, ElemType *E2)
{
    printf("Compare Struct ElemType\n");
    JudgeElemTypePointerIsNull(E1);
    JudgeElemTypePointerIsNull(E2);
    if(strcmp(E1->StudentNum,E2->StudentNum) != 0)
    {
        return FailFlag;
    }
    if(strcmp(E1->StudentName,E2->StudentName) != 0)
    {
        return FailFlag;
    }
    if((E1->StudentScore) != (E2->StudentScore))
    {
        return FailFlag;
    }
    return SuccessFlag;
}
(3)参数说明
参数名说明
E1需要比较的结构体1。
E2需要比较的结构体2。

3、LocateElemPointer

(1)用途

在链表L中找到与E相等的结构体返回对应指针。

(2)函数定义
ElemType * LocateElemPointer(LinkList *L, ElemType E)
{
    printf("Locate Element Pointer\n");
    JudgePointerNull(L);
    ElemType *p = L->ElemArray->NextPointer;
    int i = 0;
    while(p)
    {
        if(CmpElemType(p,&E) == SuccessFlag)
        {
            i++;
            printf("Pointer : %p, Locate Link List Elem Success\n",p);
            PrintPretty();
            return p;
        }
        p = p->NextPointer;
        i++;
    }
    if(i != L->ElemArrayLen)
    {
        printf("ElemArrayLen != Actual Link List Len, Exception Exit!!!\n");
        exit(ExceptionExitFlag);
    }
    printf("Locate Link List Elem Fail!!!\n");
    PrintPretty();
    return NULL;
}
(3)参数说明
参数名说明
L需要搜索的链式表。
E需要查找的数据。

4、LocateElemPosition

(1)用途

在链表L中找到与E相等的结构体返回对应位置。

(2)函数定义
int LocateElemPosition(LinkList *L, ElemType E)
{
    printf("Locate Element Position\n");
    JudgePointerNull(L);
    ElemType *p = L->ElemArray->NextPointer;
    int i = 0;
    while(p)
    {
        if(CmpElemType(p,&E) == SuccessFlag)
        {
            i++;
            printf("Position : %d, Locate Link List Elem Success\n",i);
            PrintPretty();
            return i;
        }
        p = p->NextPointer;
        i++;
    }
    if(i != L->ElemArrayLen)
    {
        printf("ElemArrayLen != Actual Link List Len, Exception Exit!!!\n");
        exit(ExceptionExitFlag);
    }
    printf("Locate Link List Elem Fail!!!\n");
    PrintPretty();
    return 0;
}
(3)参数说明
参数名说明
L需要搜索的链式表。
E需要查找的数据。

5、InsertLinkListElem

(1)用途

在链表L的ElemPosition位置插入元素VarElem。

(2)函数定义
//在插入数据时,不能直接用传入参数VarElem对链表L进行指针赋值,也就是注释掉的两行,会导致后续ClearLinkListElem执行时,提示:double free or corruption (out)。
//ClearLinkListElem代码中并没有多次free,改为注释两行上面的五行,问题得到解决。
Status InsertLinkListElem(LinkList *L, int ElemPosition, ElemType *VarElem)
{
    JudgePointerNull(L);
    printf("ElemPosition : %d\n",ElemPosition);
    PrintElemType(VarElem);
    if(ElemPosition < 1 || ElemPosition > L->ElemArrayLen + 1)
    {
        printf("Error ,Need 1 <= ElemPosition <= %d\n",L->ElemArrayLen + 1);
        PrintPretty();
        return FailFlag;
    }
    int i = 0;
    ElemType *p = L->ElemArray;
    while(p)
    {
        if(i == ElemPosition - 1)
        {
            break;
        }
        p = p->NextPointer;
        i++;
    }

    ElemType *TmpElem = (ElemType *)MyMalloc(sizeof(ElemType));
    InitElemType(TmpElem);
    CopyElemTypeData(TmpElem,VarElem);
    TmpElem->NextPointer = p->NextPointer;
    p->NextPointer = TmpElem;

    //VarElem->NextPointer = p->NextPointer;
    //p->NextPointer = VarElem;
    
    L->ElemArrayLen++;
    printf("Insert Data Success\n");
    PrintPretty();
    return SuccessFlag;
}

(3)参数说明
参数名说明
L需要插入数据的链式表。
ElemPosition需要插入的位置。
VarElem需要插入的数据。

三、测试代码

1、LinearTable_LinkList.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "LinearTable_LinkList.h"

void PrintPretty()
{
    printf("*********************************\n");
}

void PrintPretty_V1()
{
    printf("################\n");
}

void *MyMalloc(size_t size)
{
    void *Result = (void *)malloc(size);
    if(Result == NULL)
    {
        printf("malloc Function Exec Fail , Out Of Memory ,Exit!!!\n");
        exit(ExceptionExitFlag);
    }
    return Result;
}

void JudgePointerNull(LinkList *L)
{
    if(!L)
    {
        printf("Pointer Is Null ,Exit !\n");
        exit(ExceptionExitFlag);
    }
}

void JudgeElemTypePointerIsNull(ElemType *E)
{
    if(!E)
    {
        printf("Pointer Is Null ,Exit !\n");
        exit(ExceptionExitFlag);
    }
}

Status InitElemType(ElemType *E)
{
    JudgeElemTypePointerIsNull(E);
    memset(E->StudentNum , '\0', sizeof(char) * StudentNumLen);
    memset(E->StudentName, '\0', sizeof(char) * StudentNameLen);
    E->StudentScore = 0;
    E->NextPointer  = NULL;
    printf("Init ElemType Success\n");
    PrintPretty();
    return SuccessFlag;
}

Status InitLinkList(LinkList *L)
{
    JudgePointerNull(L);
    //L = (LinkList *)MyMalloc(sizeof(LinkList));
    L->ElemArray = (ElemType *)MyMalloc(sizeof(ElemType));
    InitElemType(L->ElemArray);
    L->ElemArrayLen = 0;
    printf("Init LinkList Success\n");
    PrintPretty();
    return SuccessFlag;
}

void PrintLinkList(LinkList *L)
{
    printf("Print Link List\n");
    JudgePointerNull(L);
    printf("Link List Pointer     : %p\n",L);
    PrintPretty_V1();
    ElemType *p = L->ElemArray;
    while(p)
    {
        printf("CurrentPointer        : %p\n",p);
        printf("StudentNum            : %s\n",p->StudentNum);
        printf("StudentName           : %s\n",p->StudentName);
        printf("StudentScore          : %d\n",p->StudentScore);
        printf("NextPointer           : %p\n",p->NextPointer);
        PrintPretty_V1();
        p = p->NextPointer;
    }
    printf("ElemArrayLen          : %d\n",L->ElemArrayLen);
    PrintPretty();
}

void PrintElemType(ElemType *E)
{
    printf("Print Elem Type\n");
    JudgeElemTypePointerIsNull(E);
    printf("StudentNum            : %s\n",E->StudentNum);
    printf("StudentName           : %s\n",E->StudentName);
    printf("StudentScore          : %d\n",E->StudentScore);
    printf("NextPointer           : %p\n",E->NextPointer);
    PrintPretty();
}

int JudgeLinkListIsEmpty(LinkList *L)
{
    JudgePointerNull(L);
    if(L->ElemArrayLen == 0)
    {
        printf("Link List Is Empty\n");
        PrintPretty();
        return SuccessFlag;
    }
    else
    {
        printf("Link List Is Not Empty\n");
        PrintPretty();
        return FailFlag;
    }
}

void DestroyLinkList(LinkList *L)
{
    printf("Start Destroy Link List\n");
    JudgePointerNull(L);
    ElemType *p = L->ElemArray;
    ElemType *q = NULL;
    while(p)
    {
        q = p->NextPointer;
        printf("Free Pointer          : %p\n",p);
        free(p);
        p = q;
    }
    L->ElemArrayLen = 0;
    free(L);
    printf("Free Link List Pointer: %p\n",L);
    L = NULL;
    printf("Destroy Link List Success !!!\n");
    PrintPretty();
}

Status ClearLinkListElem(LinkList *L)
{
    printf("Start Clear Link List Elem\n");
    JudgePointerNull(L);
    L->ElemArrayLen = 0;
    ElemType *p = L->ElemArray->NextPointer;
    ElemType *q = NULL;
    while(p)
    {
        q = p->NextPointer;
        printf("Free Pointer          : %p\n",p);
        free(p);
        p = q;
    }
    L->ElemArray->NextPointer = NULL;
    printf("Clear Link List Elem Success !!!\n");
    PrintPretty();
    return SuccessFlag;
}

int GetLinkListLen(LinkList *L)
{
    JudgePointerNull(L);
    printf("Get Link List Len     : %d\n",L->ElemArrayLen);
    PrintPretty();
    return L->ElemArrayLen;
}

Status CopyElemTypeData(ElemType *Dest, ElemType *Src)
{
    printf("Copy Elem Type Data\n");
    strcpy(Dest->StudentNum,Src->StudentNum);
    strcpy(Dest->StudentName,Src->StudentName);
    Dest->StudentScore = Src->StudentScore;
    Dest->NextPointer  = Src->NextPointer;
    PrintPretty();
    return SuccessFlag;
}

int GetLinkListElem(LinkList *L, int ElemPosition, ElemType *VarElem)
{
    JudgePointerNull(L);
    if(ElemPosition < 1 || ElemPosition > L->ElemArrayLen)
    {
        printf("Error ElemPosition : %d, Need 1 <= ElemPosition <= ElemArrayLen(%d)\n",ElemPosition,L->ElemArrayLen);
        PrintPretty();
        return FailFlag;
    }
    int i;
    ElemType *p = L->ElemArray;
    for(i=1; i<=ElemPosition; i++)
    {
        p = p->NextPointer;
    }
    CopyElemTypeData(VarElem,p);
    PrintElemType(VarElem);
    printf("ElemPosition          : %d ,Get Data Success\n",ElemPosition);
    PrintPretty();
    return SuccessFlag;
}

Status CmpElemType(ElemType *E1, ElemType *E2)
{
    printf("Compare Struct ElemType\n");
    JudgeElemTypePointerIsNull(E1);
    JudgeElemTypePointerIsNull(E2);
    if(strcmp(E1->StudentNum,E2->StudentNum) != 0)
    {
        return FailFlag;
    }
    if(strcmp(E1->StudentName,E2->StudentName) != 0)
    {
        return FailFlag;
    }
    if((E1->StudentScore) != (E2->StudentScore))
    {
        return FailFlag;
    }
    return SuccessFlag;
}

ElemType * LocateElemPointer(LinkList *L, ElemType E)
{
    printf("Locate Element Pointer\n");
    JudgePointerNull(L);
    ElemType *p = L->ElemArray->NextPointer;
    int i = 0;
    while(p)
    {
        if(CmpElemType(p,&E) == SuccessFlag)
        {
            i++;
            printf("Pointer : %p, Locate Link List Elem Success\n",p);
            PrintPretty();
            return p;
        }
        p = p->NextPointer;
        i++;
    }
    if(i != L->ElemArrayLen)
    {
        printf("ElemArrayLen != Actual Link List Len, Exception Exit!!!\n");
        exit(ExceptionExitFlag);
    }
    printf("Locate Link List Elem Fail!!!\n");
    PrintPretty();
    return NULL;
}

int LocateElemPosition(LinkList *L, ElemType E)
{
    printf("Locate Element Position\n");
    JudgePointerNull(L);
    ElemType *p = L->ElemArray->NextPointer;
    int i = 0;
    while(p)
    {
        if(CmpElemType(p,&E) == SuccessFlag)
        {
            i++;
            printf("Position : %d, Locate Link List Elem Success\n",i);
            PrintPretty();
            return i;
        }
        p = p->NextPointer;
        i++;
    }
    if(i != L->ElemArrayLen)
    {
        printf("ElemArrayLen != Actual Link List Len, Exception Exit!!!\n");
        exit(ExceptionExitFlag);
    }
    printf("Locate Link List Elem Fail!!!\n");
    PrintPretty();
    return 0;
}

//在插入数据时,不能直接用传入参数VarElem对链表L进行指针赋值,也就是注释掉的两行,会导致后续ClearLinkListElem执行时,提示:double free or corruption (out)。
//ClearLinkListElem代码中并没有多次free,改为注释两行上面的五行,问题得到解决。
Status InsertLinkListElem(LinkList *L, int ElemPosition, ElemType *VarElem)
{
    JudgePointerNull(L);
    printf("ElemPosition : %d\n",ElemPosition);
    PrintElemType(VarElem);
    if(ElemPosition < 1 || ElemPosition > L->ElemArrayLen + 1)
    {
        printf("Error ,Need 1 <= ElemPosition <= %d\n",L->ElemArrayLen + 1);
        PrintPretty();
        return FailFlag;
    }
    int i = 0;
    ElemType *p = L->ElemArray;
    while(p)
    {
        if(i == ElemPosition - 1)
        {
            break;
        }
        p = p->NextPointer;
        i++;
    }

    ElemType *TmpElem = (ElemType *)MyMalloc(sizeof(ElemType));
    InitElemType(TmpElem);
    CopyElemTypeData(TmpElem,VarElem);
    TmpElem->NextPointer = p->NextPointer;
    p->NextPointer = TmpElem;

    //VarElem->NextPointer = p->NextPointer;
    //p->NextPointer = VarElem;
    
    L->ElemArrayLen++;
    printf("Insert Data Success\n");
    PrintPretty();
    return SuccessFlag;
}

2、LinearTable_LinkList.h

#ifndef LinearTable_LinkList_H
#define LinearTable_LinkList_H

#define InsertDataArrayLen 6

#define ExceptionExitFlag -1
#define SuccessFlag        1
#define FailFlag           0
#define ElemArrayMaxLen   10
#define StudentNumLen      8
#define StudentNameLen     8

typedef int Status;

typedef struct ElemType
{
    char             StudentNum[StudentNumLen];
    char             StudentName[StudentNameLen];
    int              StudentScore;
    struct ElemType *NextPointer;
}ElemType;

typedef struct 
{
    ElemType *ElemArray;
    int      ElemArrayLen;
}LinkList;

void *MyMalloc(size_t size);
Status InitElemType(ElemType *E);
Status InitLinkList(LinkList *L);
void JudgePointerNull(LinkList *L);
void JudgeElemTypePointerIsNull(ElemType *E);
void PrintLinkList(LinkList *L);
int JudgeLinkListIsEmpty(LinkList *L);
void DestroyLinkList(LinkList *L);
Status ClearLinkListElem(LinkList *L);
int GetLinkListLen(LinkList *L);
Status CopyElemTypeData(ElemType *Dest, ElemType *Src);
int GetLinkListElem(LinkList *L, int ElemPosition, ElemType *VarElem);
void PrintElemType(ElemType *E);
Status CmpElemType(ElemType *E1, ElemType *E2);
ElemType * LocateElemPointer(LinkList *L, ElemType E);
int LocateElemPosition(LinkList *L, ElemType E);
Status InsertLinkListElem(LinkList *L, int ElemPosition, ElemType *VarElem);

void PrintPretty();
void PrintPretty_V1();
#endif

3、main.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "LinearTable_LinkList.h"

int main()
{
    LinkList *L = (LinkList *)MyMalloc(sizeof(LinkList));
    ElemType *VarElem = (ElemType *)MyMalloc(sizeof(ElemType));
    ElemType *InsertElemArray = (ElemType *)MyMalloc(sizeof(ElemType) * InsertDataArrayLen);
    int i;
    for(i=0; i<InsertDataArrayLen; i++)
    {
        InitElemType(&(InsertElemArray[i]));
        strcpy(InsertElemArray[i].StudentNum ,"X666");
        strcpy(InsertElemArray[i].StudentName,"Sun");
        InsertElemArray[i].StudentScore = i + 100;
    }

    InitLinkList(L);
    PrintLinkList(L);
    for(i=0; i<InsertDataArrayLen; i++)
    {
        InsertLinkListElem(L, 1, &(InsertElemArray[i]));
    }
    PrintLinkList(L);
    GetLinkListElem(L, InsertDataArrayLen - 1, VarElem);
    //PrintElemType(VarElem);
    LocateElemPointer(L,*VarElem);
    LocateElemPosition(L,*VarElem);
    PrintElemType(VarElem);
    JudgeLinkListIsEmpty(L);
    GetLinkListLen(L);
    ClearLinkListElem(L);
    PrintLinkList(L);
    DestroyLinkList(L);

    free(VarElem);
    free(InsertElemArray);
    L               = NULL;
    VarElem         = NULL;
    InsertElemArray = NULL;
    return SuccessFlag;
}

4、makefile

CC = gcc
CFLAG_EXEC = -Wall -O3
CFLAG_ALIAS = -o
RM_COMM = rm -rf

all : main

main : 
	$(CC) $(CFLAG_EXEC) LinearTable_LinkList.c main.c $(CFLAG_ALIAS) Test_LinearTable_LinkList

clean : 
	$(RM_COMM) Test_LinearTable_LinkList

四、编译测试

[gbase@czg2 LinearTable_LinkList]$ make clean
rm -rf Test_LinearTable_LinkList

[gbase@czg2 LinearTable_LinkList]$ make
gcc -Wall -O3 LinearTable_LinkList.c main.c -o Test_LinearTable_LinkList

[gbase@czg2 LinearTable_LinkList]$ ./Test_LinearTable_LinkList 
Init ElemType Success
*********************************
Init ElemType Success
*********************************
Init ElemType Success
*********************************
Init ElemType Success
*********************************
Init ElemType Success
*********************************
Init ElemType Success
*********************************
Init ElemType Success
*********************************
Init LinkList Success
*********************************
Print Link List
Link List Pointer     : 0x1552010
################
CurrentPointer        : 0x1552130
StudentNum            : 
StudentName           : 
StudentScore          : 0
NextPointer           : (nil)
################
ElemArrayLen          : 0
*********************************
ElemPosition : 1
Print Elem Type
StudentNum            : X666
StudentName           : Sun
StudentScore          : 100
NextPointer           : (nil)
*********************************
Init ElemType Success
*********************************
Copy Elem Type Data
*********************************
Insert Data Success
*********************************
ElemPosition : 1
Print Elem Type
StudentNum            : X666
StudentName           : Sun
StudentScore          : 101
NextPointer           : (nil)
*********************************
Init ElemType Success
*********************************
Copy Elem Type Data
*********************************
Insert Data Success
*********************************
ElemPosition : 1
Print Elem Type
StudentNum            : X666
StudentName           : Sun
StudentScore          : 102
NextPointer           : (nil)
*********************************
Init ElemType Success
*********************************
Copy Elem Type Data
*********************************
Insert Data Success
*********************************
ElemPosition : 1
Print Elem Type
StudentNum            : X666
StudentName           : Sun
StudentScore          : 103
NextPointer           : (nil)
*********************************
Init ElemType Success
*********************************
Copy Elem Type Data
*********************************
Insert Data Success
*********************************
ElemPosition : 1
Print Elem Type
StudentNum            : X666
StudentName           : Sun
StudentScore          : 104
NextPointer           : (nil)
*********************************
Init ElemType Success
*********************************
Copy Elem Type Data
*********************************
Insert Data Success
*********************************
ElemPosition : 1
Print Elem Type
StudentNum            : X666
StudentName           : Sun
StudentScore          : 105
NextPointer           : (nil)
*********************************
Init ElemType Success
*********************************
Copy Elem Type Data
*********************************
Insert Data Success
*********************************
Print Link List
Link List Pointer     : 0x1552010
################
CurrentPointer        : 0x1552130
StudentNum            : 
StudentName           : 
StudentScore          : 0
NextPointer           : 0x1552250
################
CurrentPointer        : 0x1552250
StudentNum            : X666
StudentName           : Sun
StudentScore          : 105
NextPointer           : 0x1552220
################
CurrentPointer        : 0x1552220
StudentNum            : X666
StudentName           : Sun
StudentScore          : 104
NextPointer           : 0x15521f0
################
CurrentPointer        : 0x15521f0
StudentNum            : X666
StudentName           : Sun
StudentScore          : 103
NextPointer           : 0x15521c0
################
CurrentPointer        : 0x15521c0
StudentNum            : X666
StudentName           : Sun
StudentScore          : 102
NextPointer           : 0x1552190
################
CurrentPointer        : 0x1552190
StudentNum            : X666
StudentName           : Sun
StudentScore          : 101
NextPointer           : 0x1552160
################
CurrentPointer        : 0x1552160
StudentNum            : X666
StudentName           : Sun
StudentScore          : 100
NextPointer           : (nil)
################
ElemArrayLen          : 6
*********************************
Copy Elem Type Data
*********************************
Print Elem Type
StudentNum            : X666
StudentName           : Sun
StudentScore          : 101
NextPointer           : 0x1552160
*********************************
ElemPosition          : 5 ,Get Data Success
*********************************
Locate Element Pointer
Compare Struct ElemType
Compare Struct ElemType
Compare Struct ElemType
Compare Struct ElemType
Compare Struct ElemType
Pointer : 0x1552190, Locate Link List Elem Success
*********************************
Locate Element Position
Compare Struct ElemType
Compare Struct ElemType
Compare Struct ElemType
Compare Struct ElemType
Compare Struct ElemType
Position : 5, Locate Link List Elem Success
*********************************
Print Elem Type
StudentNum            : X666
StudentName           : Sun
StudentScore          : 101
NextPointer           : 0x1552160
*********************************
Link List Is Not Empty
*********************************
Get Link List Len     : 6
*********************************
Start Clear Link List Elem
Free Pointer          : 0x1552250
Free Pointer          : 0x1552220
Free Pointer          : 0x15521f0
Free Pointer          : 0x15521c0
Free Pointer          : 0x1552190
Free Pointer          : 0x1552160
Clear Link List Elem Success !!!
*********************************
Print Link List
Link List Pointer     : 0x1552010
################
CurrentPointer        : 0x1552130
StudentNum            : 
StudentName           : 
StudentScore          : 0
NextPointer           : (nil)
################
ElemArrayLen          : 0
*********************************
Start Destroy Link List
Free Pointer          : 0x1552130
Free Link List Pointer: 0x1552010
Destroy Link List Success !!!
*********************************
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值