码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构第二天、线性表的链式表示和实现

时间:2015-07-10 18:22:55      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:

  今天是学习数据结构的第二天,让我们来一起重温数据结构中极为经典的链表。

  在复习链表之前我们来复习一个C/C++中很重要的知识点

#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct node
{
    ElemType data;
    struct node *next;
}LinkList;
void InitList(LinkList *L)//初始化单链表
{
    L=(LinkList *)malloc(sizeof(LinkList));
    L->next=NULL;
}
int main()
{
    int i;
    ElemType e;
    LinkList *L;
    InitList(L);
}

很多同学会说上述代码不就是完成链表初始化的一段代码吗,没有什么特殊的。其实,这段代码是会报错的。因为它根本没有初始化链表。

原因是InitList(L)实际上是对值的传递,和swap()函数的原理类似,传值调用传递的时原来数据的副本,副本是在栈上调用的,在函数执行完成后会自动释放,也没有返回到main函数的具体值,所以会失败。

正确方法是下面这种方法

#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct node
{
    ElemType data;
    struct node *next;
}LinkList;
void InitList(LinkList **L)//初始化单链表
{
    *L=(LinkList *)malloc(sizeof(LinkList));
    (*L)->next=NULL;
}
int main()
{
    int i;
    ElemType e;
    LinkList *L;
    InitList(&L);
}

也就是传入指针的地址,即指针的指针。

在我的代码中,我才去了另外一种方法,即初始化函数返回时将指针赋值给main函数里的局部变量,这样也可以解决这种问题,具体代码如下:

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

typedef struct Node
{
    int Data;
    struct Node *Next;
} List;

//创建具有头结点的链表
List *CreateList(int n)
{
    List *LinkList = (List *)malloc(sizeof(List));
    LinkList->Next = NULL;

    for (int i = n; i > 0; --i)
    {
        List *p = (List *)malloc(sizeof(List));
        scanf("%d", &p->Data);
        p->Next = LinkList->Next;
        LinkList->Next = p;
    }
    return LinkList;
}

//添加
void Insert(List *LinkList, int n, int e)
{
    List *p = LinkList;
    int j = 0;

    while (p && j < n-1) {
        p = p->Next;
        ++j;
    }

    if (!p || j > n-1)
    {
        printf("Error\n");
        return;
    }

    List *s = (List *)malloc(sizeof(List));
    s->Data = e;
    s->Next = p->Next;
    p->Next = s;
    return;
}

//删除
void Delete(List *LinkList, int n)
{
    List *p = LinkList;
    int j = 0;

    while (p->Next && j < n-1) {
        p = p->Next;
        ++j;
    }

    if (p->Next == NULL || j > n-1)
    {
        printf("Error\n");
        return;
    }

    List *q = p->Next;
    p->Next = q->Next;

    free(q);
    return;
}

//已知单链线性表La和Lb的元素按值非递减排列
//归并La和Lb得到新的单链线性表Lc,Lc也按值非递减排列
List *MergeList(List *la, List *lb)
{
    List *pa = la->Next;
    List *pb = lb->Next;
    List *lc = la;
    List *pc = lc;
    while (pa && pb) {
        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;
    free(lb);
    return la;
}

//遍历
void Traverse(List *LinkList)
{
    List *q = LinkList->Next;

    while (q != NULL) {
        printf("%d\n", q->Data);
        q = q->Next;
    }
    return;
}

int main(int argc, char const *argv[])
{
    List *list_link;
    list_link =  CreateList(4);
    printf("输出创建的链表\n");
    Traverse(list_link);
    //printf("%d\n", list_link->Next->Data);
    printf("输出删除具体节点后的链表\n");
    Delete(list_link, 2);
    Traverse(list_link);

    printf("输出la,lb归并后的链表测试\n");
    List *la, *lb, *lc;
    printf("请输入la链表\n");
    la = CreateList(3);
    printf("请输入lb链表\n");
    lb = CreateList(4);
    lc = MergeList(la, lb);
    Traverse(lc);
    return 0;
}

Insert()和Delete()的时间复杂度也都是O(n)量级的。

还有一个要主要的点是在做MergeList(归并操作)时,Lc链表只是将La和Lb链表中的节点重新链接在一起了,没有重新malloc空间。

数据结构第二天、线性表的链式表示和实现

标签:

原文地址:http://www.cnblogs.com/wgqtmac/p/4636362.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!