线性表链式存储结构的表示和实现

基本概念

1、线性表的顺序存储结构的缺点是插入和删除时需要移动大量元素,这会消耗大量时间,可以选择链式存储结构来解决这个问题。
2、链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。意味着,这些数据元素可以存储在内存中未被占用的任意位置。
3、在顺序存储结构中,每个数据元素只需存数据元素的信息,而链式存储结构中,除了要存储数据元素的信息,还要存储它的后继元素的存储地址。
4、我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称为指针或链。这两部分信息组成数据源的存储映像,称为结点。
5、n个结点链结成一个链表,即为线性表的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表。头指针和头结点的异同如下描述:
头指针
(1)头指针是链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针;
(2)头指针具有标识作用,所以常用头指针冠以链表的名字;
(3)无论链表是否为空,头指针均不为空,头指针是链表的必要元素。
头结点
(1)头结点是为了操作的统一和方重点内容便而设立的,放在第一个元素的结点之前,其数据域一般无意义(也可以存放链表的长度);
(2)有了头结点,对在第一元素之前插入结点和删除第一节点,其操作与其它结点的操作就统一了;
(3)头结点不一定是链表必须要素。
单链表结构和顺序存储结构的对比如图所示:

这里写图片描述
结论:(1)若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。若需要频繁插入和删除时,宜采用单链表结构。
(2)当线性表中的元素个数变化较大或者根本不知道有多大时,最好采用单链表结构,这样可以不需要考虑存储空间的大小问题。

带头结点的单链表的表示和实现

"linklist.h"

#pragma once
typedef int ELEM_TYPE;

typedef struct LNode
{
    ELEM_TYPE data;
    struct LNode *next;
}LNode,*LinkList;

//初始化头结点
void init_linklist(LinkList *phead);
//头插
void insert_head(LinkList *phead,ELEM_TYPE val);
//尾插
void insert_tail(LinkList *phead,ELEM_TYPE val);
int get_length(LinkList *phead);
void show(LinkList *phead);
void destroy_list(LinkList *phead);
bool is_empty(LinkList *phead);
//根据位置插入
void insert_pos(LinkList *phead,int pos,ELEM_TYPE val);
bool delete_pos(LinkList *phead,int pos);
//根据位置获得结点
void get_node(LinkList *phead,int pos,LinkList *node);
//修改结点值
void update_node(LinkList *phead,int pos,ELEM_TYPE new_val);
//通过值查找位置
int search(LinkList *phead,ELEM_TYPE val);
//根据值查找结点
LNode* getNodeByValue(LinkList *phead,ELEM_TYPE val);
bool deleteByValue(LinkList *phead,ELEM_TYPE val);
//删除尾结点
bool delete_tail(LinkList *phead);
//从尾销毁链表
void destroyByLast(LinkList *phead);
//从尾创建指定长度的单链表
void createListTail(LinkList *phead,int n);
//合并单链表1
void union_list(LinkList *phead1,LinkList *phead2,LinkList *pc);
//合并单链表2
void mergeList(LinkList *phead1,LinkList *phead2,LinkList *phead3);
//逆转单链表
void reverse_list(LinkList *phead);
//将值插入有序的单链表,并保持有序
void insert_sort(LinkList *phead,ELEM_TYPE x);
//合并单链表并逆转
void merge_reverse_list(LinkList *la,LinkList *lb,LinkList *lc);

"linklist.cpp"

#include "linklist.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stack>

//初始化头结点
void init_linklist(LinkList *phead)
{
    assert(NULL != phead);
    *phead = (LinkList)malloc(sizeof(LNode));
    if (NULL == *phead)
    {
        exit(1);
    }
    (*phead)->data = 0;
    (*phead)->next = NULL;
}

void insert_head(LinkList *phead,ELEM_TYPE val)
{
    assert(*phead != NULL);
    LinkList p,q;
    p = *phead;
    q = (LNode *)malloc(sizeof(LNode));
    if (NULL == q)
    {
        exit(1);
    }
    q->data = val;
    q->next = p->next;
    p->next = q;
}

void insert_tail(LinkList *phead,ELEM_TYPE val)
{
    assert(*phead != NULL);
    LinkList p,q;

    p = *phead;
    while (p->next != NULL)
    {
        p = p->next;
    }

    q = (LNode *)malloc(sizeof(LNode));
    if (NULL == q)
    {
        exit(1);
    }

    q->data = val;
    q->next = NULL;
    p->next = q;
}

bool is_empty(LinkList *phead)
{
    assert(*phead != NULL);
    return (*phead)->next == NULL;  
}

void insert_pos(LinkList *phead,int pos,ELEM_TYPE val)
{
    assert(*phead != NULL);
    LinkList p,q;
    p = *phead;
    int len = get_length(phead);
    assert(pos >= 0 && pos <= len);

    if (len == 0)
    {
        q = (LNode *)malloc(sizeof(LNode));
        if (NULL == q)
        {
            exit(1);
        }
        q->data = val;
        q->next = NULL;
        p->next = q;
        return;
    }

    int i = 0;
    while (p->next != NULL)
    {
        if (i==pos)
        {
            q = (LNode *)malloc(sizeof(LNode));
            if (NULL == q)
            {
                exit(1);
            }
            q->data = val;
            q->next = p->next;
            p->next = q;
            break;
        }
        ++i;
        p = p->next; 
    }
}

bool delete_pos(LinkList *phead,int pos)
{
    assert(*phead != NULL);
    LinkList p,q;
    p = *phead;
    int len = get_length(phead);
    assert(pos >= 0 && pos < len);

    int i = 0;
    while (p->next != NULL)
    {
        if (i==pos)
        {
            q = p->next;
            p->next = q->next;
            free(q);
            return true;
        }
        ++i;
        p = p->next;
    }

    return false;
}

int get_length(LinkList *phead)
{
    assert(*phead != NULL);
    LinkList p;
    p = *phead;
    int len = 0;
    while (p->next != NULL)
    {
        len++;
        p = p->next;
    }
    return len;
}

void show(LinkList *phead)
{
    assert(*phead != NULL);
    LinkList p;
    p = *phead;
    if (p->next==NULL)
    {
        printf("当前元素为空\n");
        return;
    }

    while (p->next != NULL)
    {
        printf("data:%d\n",p->next->data);
        p = p->next;
    }
}

void destroy_list(LinkList *phead)
{
    assert(*phead != NULL);
    LinkList p,q;
    p = *phead;
    while (p != NULL)
    {
        q = p->next;
        free(p);
        p = q;
    }
    *phead = NULL;
}

void get_node(LinkList *phead,int pos,LinkList *node)
{
    assert(*phead != NULL);
    LinkList p;
    p = *phead;
    int len = get_length(phead);
    assert(pos >= 0 && pos < len);

    int i = 0;
    while (p->next != NULL)
    {
        if (i==pos)
        {
            *node = p->next;
            break;
        }
        i++;
        p = p->next;
    }
}

void update_node(LinkList *phead,int pos,ELEM_TYPE new_val)
{
    assert(*phead != NULL);
    LinkList p;
    p = *phead;
    int len = get_length(phead);
    assert(pos >= 0 && pos < len);
    int i = 0;
    while (p->next != NULL)
    {
        if (i==pos)
        {
            p->next->data = new_val;
            break;
        }
        i++;
        p = p->next;
    }
}

int search(LinkList *phead,ELEM_TYPE val)
{
    assert(*phead != NULL);
    LinkList p;
    p = *phead;
    int i = 0;
    while (p->next != NULL)
    {
        if (p->next->data == val)
        {
            return i;
        }
        i++;
        p = p->next;
    }
    return -1;
}

LNode* getNodeByValue(LinkList *phead,ELEM_TYPE val)
{
    assert(*phead != NULL);
    LinkList p;
    p = *phead;
    int i = 0;
    while (p->next != NULL)
    {
        if (p->next->data == val)
        {
            return p->next;
        }
        i++;
        p = p->next;
    }
    return NULL;
}

bool deleteByValue(LinkList *phead,ELEM_TYPE val)
{
    assert(*phead != NULL);
    LinkList p,q;
    p = *phead;

    int i = 0;
    while (p->next != NULL)
    {
        if (p->next->data == val)
        {
            q = p->next;
            p->next = q->next;
            free(q);
            return true;
        }
        ++i;
        p = p->next;
    }
    return false;
}

bool delete_tail(LinkList *phead)
{
    assert(*phead != NULL);
    LinkList p,q;
    p = *phead;
    if (p->next == NULL)
    {
        return false;
    }
    int i = 0;
    while (p->next != NULL)
    {
        ++i;
        q = p;
        p = p->next;
    }
    free(p);
    q->next = NULL;
    return true;
}

void destroyByLast(LinkList *phead)
{
    assert(*phead != NULL);
    LinkList p,q;
    p = *phead;
    while (p->next != NULL)
    {
        while (p->next != NULL)
        {
            q = p;
            p = p->next;
        }
        free(p);
        q->next = NULL;
        p = *phead;
    }
    free(*phead);
    *phead = NULL;
}

void createListTail(LinkList *phead,int n)
{
    assert(phead != NULL);
    *phead = (LNode *)malloc(sizeof(LNode));
    if(*phead == NULL)
    {
        exit(1);
    }
    (*phead)->data = 0;
    (*phead)->next = NULL;

//  LinkList p,r;
//  r = *phead;
    int i;
    for(i=0;i<n;++i)
    {
        //p = (LNode *)malloc(sizeof(LNode));
        //if(p == NULL)
        //{
        //  exit(1);
        //}
        //p->data = i;
        //p->next = NULL;
        //r->next = p;
        //r = p;

        insert_head(phead,i+1);
    }
}

//合并两个从小到大排序的单链表
void union_list(LinkList *phead1,LinkList *phead2,LinkList *pc)
{
    assert(*phead1 != NULL && *phead2 != NULL && *pc != NULL);

    LinkList p1 = (*phead1)->next;
    LinkList p2 = (*phead2)->next;

    while(p1 != NULL && p2 != NULL)
    {
        if(p1->data >= p2->data)
        {
            insert_tail(pc,p2->data);
            p2 = p2->next;
        }
        else
        {
            insert_tail(pc,p1->data);
            p1 = p1->next;
        }
    }

    while (p1 != NULL)
    {
        insert_tail(pc,p1->data);
        p1 = p1->next;
    }

    while (p2 != NULL)
    {
        insert_tail(pc,p2->data);
        p2 = p2->next;
    }
}

//合并两个从小到大排序的单链表
void mergeList(LinkList *phead1,LinkList *phead2,LinkList *phead3)
{
    assert(*phead1 != NULL && *phead2 != NULL && *phead3 != NULL);
    LinkList pa = (*phead1)->next;
    LinkList pb = (*phead2)->next;
    LinkList pc = *phead3;

    while (pa != NULL && pb != NULL)
    {
        if(pa->data <= pb->data)
        {
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }
        else
        {
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    }
    pc->next = (pa != NULL ? pa : pb); 

}

//尾插法逆转链表
void reverse_list(LinkList *phead)
{
    assert(*phead != NULL);

    LinkList pNode,pPrev;
    pNode = (*phead)->next;
    pPrev = NULL;
    while (pNode != NULL)
    {
        LinkList pNext = pNode->next;
        //如果遇到最后一个结点
        if (pNext == NULL)
        {
            (*phead)->next = pNode;
        }
        //逆转指针
        pNode->next = pPrev;
        pPrev = pNode;
        pNode = pNext;
    }
}

void insert_sort(LinkList *phead,ELEM_TYPE x)
{
    assert(*phead != NULL);
    LinkList p;
    p = *phead;
    LinkList t = (LNode *)malloc(sizeof(LNode));
    t->data = x;
    t->next = NULL;

    while(p->next != NULL) 
    {
        if(p->next->data > x)
        {
            t->next = p->next;
            p->next = t;
            break;
        }
        p = p->next;
    }

    if(x > p->data)
    {
        p->next = t;
    }
}

//合并两个从小到大排序的单链表,并逆转
void merge_reverse_list(LinkList *la,LinkList *lb,LinkList *lc)
{
    assert(*la != NULL && *lb != NULL && *lc != NULL);
    LinkList pa,pb,pc;
    pa = (*la)->next;
    pb = (*lb)->next;
    pc = *lc;
    while(pa != NULL && pb != NULL)
    {
        if(pa->data <= pb->data)
        {
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }
        else
        {
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    }
    pc->next = pa ? pa : pb;
    reverse_list(lc); 
}

"test_linklist.cpp"

#include <stdio.h>
#include "linklist.h"
#include <stdlib.h>

int main()
{
    LinkList head;
    init_linklist(&head);
    int i;
    for (i=0;i<5;++i)
    {
        insert_tail(&head,i+1);
    }
    insert_pos(&head,3,30);
    //delete_pos(&head,3);
    show(&head);

    int length = get_length(&head);
    printf("length = %d\n",length);

    //destroy_list(&head);
    //show(&head);

    //LinkList node;
    //get_node(&head,3,&node);
    //printf("node_value:%d\n",node->data);

    update_node(&head,3,15);
//  show(&head);
    //int pos = search(&head,15);
    //printf("pos = %d\n",pos);

    //LNode *node2 = getNodeByValue(&head,15);
    //printf("node_value:%d\n",node2->data);
    //deleteByValue(&head,15);
    //show(&head);

    delete_tail(&head);
//  show(&head);

    destroyByLast(&head);
//  show(&head);

    //LinkList newList;
    采用头插法
    //createListTail(&newList,5);
    //show(&newList);

    LinkList la,lb,lc;
    init_linklist(&la);
    init_linklist(&lb);
    init_linklist(&lc);
//  int i;
    for (i=0;i<4;++i)
    {
        insert_tail(&la,2*i+1);
    }
//  show(&la);
    insert_sort(&la,6);
    insert_sort(&la,2);
    insert_sort(&la,14);
//  show(&la);

//  reverse_list(&la);
//  show(&la);

    for (i=0;i<3;++i)
    {
        insert_tail(&lb,i+3);
    }
//  show(&lb);
//  merge_reverse_list(&la,&lb,&lc);
//  show(&lc);

//  union_list(&la,&lb,&lc);
//  show(&lc);

    mergeList(&la,&lb,&lc);
    show(&lc);

    return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值