IOS个人开发程序员iOS Developer

线性表的链式表示和实现

2017-04-04  本文已影响68人  小黑_Coder

继上一篇博客讨论了线性表的顺序表示和实现今天我们就来讨论和实现一下线性表的链式存储。从上一片博客分析,我们知道线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也是相邻,因此可以随机存取表中任一元素。但是这个特点也带了此存储结构的弱点,就是在插入和删除操作时需要移动大量的元素。而我们今天要讨论的线性表的链式存储结构,由于它不要求逻辑上相邻的元素位置也要相邻,因此就能很好的避免移动元素,但是会失去随机存取的优点

名词解释

线性链表

结点

数据域

指针域

单链表

线性表的单链表存储结构

typedef struct LNode {
    
    ElemType data;          //存储数据元素
    struct LNode *next;     //结点,指向直接后继元素地址
    
}SinglyLinkList;

基本操作

基本操作实现

初始化

SinglyLinkList * InitSinglyLinkList() {
    
    SinglyLinkList *linkList = (SinglyLinkList *)malloc(sizeof(SinglyLinkList));
    if (!linkList) {
        
        printf("OVERFLOW %s", __func__);
        return NULL;
    }
    linkList->data = 0;
    linkList->next = NULL;
    return linkList;
}

初始化即在堆上开辟sizeof(SinglyLinkList)大小的空间作为链表的头结点,然后将头结点的地址返回

插入元素

Status InsertElemIntoSinglyLinkList(SinglyLinkList *linkList, int index, ElemType elem) {
    
    if (index < 1 || !linkList) {
        
        return ERROR;
    }
    SinglyLinkList *listPointer = linkList;
    int counter = 1;
    while (listPointer && counter < index) {
        
        listPointer = listPointer->next;
        counter++;
    }
    if (!listPointer || counter > index) {
        
        return ERROR;
    } else {
    
        SinglyLinkList *insert = (SinglyLinkList *)malloc(sizeof(SinglyLinkList));
        if (!insert) {
            
            return OVERFLOW;
        } else {
            
            SinglyLinkList *temp = listPointer->next;
            listPointer->next = insert;
            insert->data = elem;
            insert->next = temp;
            return OK;
        }
    }
}

根据下标获取元素

Status GetElemFromSinglyLinkList(SinglyLinkList linkList, int index, ElemType *elem) {
    
    if (index < 1) {
        
        return ERROR;
    }
    SinglyLinkList *listPointer = linkList.next;
    int counter = 1;
    while (listPointer && counter < index) {
        
        listPointer = listPointer->next;
        counter++;
    }
    if (!listPointer || counter > index) {
        
        return ERROR;
    } else {
        
        *elem = listPointer->data;
        return OK;
    }
}

根据元素获取下标

Status GetIndexFromSinglyLinkList(SinglyLinkList linkList, int *index, ElemType elem) {
    
    SinglyLinkList *listPointer = linkList.next;
    int counter = 1;
    while (listPointer) {
        
        if (listPointer->data == elem) {
            
            *index = counter;
            return OK;
        }
        listPointer = listPointer->next;
        counter++;
    }
    return ERROR;
}

删除元素

Status DeleteElemFromSinglyLinkList(SinglyLinkList *linkList, int index) {
    
    if (index < 1 || !linkList) {
        
        return ERROR;
    }
    SinglyLinkList *listPointer = linkList;
    int counter = 1;
    while (listPointer && counter < index) {
        
        listPointer = listPointer->next;
        counter++;
    }
    if (!listPointer || counter > index || !listPointer->next) {
        
        return ERROR;
    } else {
        
        SinglyLinkList *temp = listPointer->next;
        listPointer->next = temp->next;
        free(temp);
        return OK;
    }
}

在删除元素之后一定要记得free(deleteLNode)

判断是否是链表中的元素

Status IsElemFromSinglyLinkList(SinglyLinkList linkList, ElemType elem) {
    
    SinglyLinkList *listPointer = linkList.next;
    while (listPointer) {
        
        if (listPointer->data == elem) {
            
            return OK;
        }
        listPointer = listPointer->next;
    }
    return ERROR;
}

在链表后面拼接元素

Status AppendElemForSinglyLinkList(SinglyLinkList *linkList, ElemType elem) {
    
    if (!linkList) {
        
        return ERROR;
    }
    SinglyLinkList *listPointer = linkList;
    while (listPointer->next) {
        
        listPointer = listPointer->next;
    }
    SinglyLinkList *append = (SinglyLinkList *)malloc(sizeof(SinglyLinkList));
    if (!append) {
        
        return OVERFLOW;
    }
    listPointer->next = append;
    append->next = NULL;
    append->data = elem;
    return OK;
}

拼接元素需要注意的时候append->next = NULL

获取链表的长度

Status LengthSinglyLinkList(SinglyLinkList linkList, int *length) {
    
    int counter = 0;
    SinglyLinkList *listPointer = linkList.next;
    while (listPointer) {
        
        counter++;
        listPointer = listPointer->next;
    }
    *length = counter;
    return OK;
}

清空链表

Status ClearSinglyLinkList(SinglyLinkList *linkList) {
    
    if (!linkList) {
        
        return ERROR;
    }
    SinglyLinkList *listPointer = linkList->next;
    while (listPointer) {
        
        SinglyLinkList *temp = listPointer;
        listPointer = listPointer->next;
        free(temp);
    }
    linkList->next = NULL;
    return OK;
}

保留头结点,此链表还可以使用

销毁链表

Status DestroySinglyLinkList(SinglyLinkList *linkList) {
    
    if (linkList) {
        
        ClearSinglyLinkList(linkList);
    }
    free(linkList);
    linkList = NULL;
    return OK;
}

会要头结点也要free,并且要将linkList = NULL不然会出现野指针,此后链表不可在使用

输出链表

Status PrintSinglyLinkList(SinglyLinkList linkList) {
    
    SinglyLinkList *listPointer = linkList.next;
    int counter = 1;
    while (listPointer) {
        
        printf("the %dth elem is %d \n", counter, listPointer->data);
        counter++;
        listPointer = listPointer->next;
    }
    return OK;
}

线性链表特点

根据对线性链表基本操作的实现我们知道,我们在插入和删除元素的时候不需要移动其他元素,每一种基本操作的时间复杂度也相对比较清晰,这里就不在过多的赘述了。下面对比线性表的顺序表说一说链表和顺序表的区别。

欢迎讨论

GitHub:https://github.com/LHCoder2016/DataStructure.git
Email:huliuworld@yahoo.com

上一篇 下一篇

猜你喜欢

热点阅读