数据结构(2)链表的实现

这个实现可能有许多的错误, 还有最后最数据结构最后的测试上, 费了不少力, 请大家看完后不吝赐教!!!

贴代码啦

LinkList.h

#ifndef _SINGLELINKLIST_H
#define _SINGLELINKLIST_H

/*这是一种简单的链表的实现方式*/
//typedef int Elemtype;

struct node;
/*刚开始这个地方写成了typedef struct *PtrToNode;最后导致无法编译*/
typedef struct node *PtrToNode;


/*在结构体后面没有定义指针,而是使用了如下的定义 ,在编译时出现left of 'next' specifies undefined struct/union '$S1'*/
typedef PtrToNode List;
typedef PtrToNode Position;


typedef struct{
    char key[15];
    char name[20];
    int age;
}Elemtype;

typedef struct node
{
    Elemtype elem;
    struct node * next;
};//*Position,*List;

/* 初始化头结点*/
/* 第一种初始化方式*/
//List InitList(List L);
/* 第二种初始化方式*/
void InitList(List *L);

/* 是不是空表*/
int IsEmpty(List L);
 
/* 判断是不是最后一个元素*/
int IsLast(List L, Position P);

/* 插入元素,倒插法,新插入的元素为表的第一个元素*/
void AddFirst(List L, Elemtype elem);

/* 插入元素,插入元素到表尾*/
void AddEnd(List L, Elemtype elem);

/* 返回特定的数据在表中位置*/
Position Find(List L, char *key);

/* 如果key找到, 则返回key对应的前一个节点*/
Position FindPrevious(List L, char *key);


/* 在特定结点的后面插入新的结点*/
int Insert(List L, Elemtype elem, char *key);

/* 删除表中某个特定元素*/
int Delete(List L, char *key);

/* 销毁表*/
void DeleteList(List L);

/*获取链表的长度*/
int Length(List L);

/*遍历*/
void traverse(List L);

#endif    /*_SINGLELINKLIST_H*/

LinkList.c

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

#include "LinkList.h"

// /* 1. 第一种初始化写法::不要这么写;*/
// /* 2. 因为表头是亚节点,所以初始化需要分配空间*/
// /* 3. 函数的返回值必须是堆变量如果是栈变量,那么在函数返回的时候就会被销毁*/
// List InitList(List L)
// {
//     L=(struct node *)malloc(sizeof(struct node));
//     L->next=NULL;
//     return L;
//     /*哑节点如果这样初始化就会出现NullPointException,当然这样的错误vc不会提示*/
//     //L = NULL;
// }

/* 0. 第二种写法*/
/* 1. 刚开始由于不懂运算优先级将*L->next=NULL,->的优先级高于*,并且最后导致编译失败*/
void InitList(List *L)
{
    *L=(List)malloc(sizeof(struct node));
    (*L)->next=NULL;
}

/* 空表返回T, 反之放回F*/
int IsEmpty(List L)
{
    return L->next == NULL;
}

/* 判断是不是最后一个元素*/
int IsLast(List L, Position P)
{
    return P->next == NULL;
}
 
/* 插入元素,倒插法,新插入的元素为表的第一个元素*/
void AddFirst(List L, Elemtype elem)
{
    Position tmpcell;

    if (!(tmpcell = (struct node *)malloc(sizeof(struct node))))
    {
        printf("节点内存分配失败啦
");
        return ;
    }
    tmpcell->elem = elem;
    tmpcell->next = L->next;
    L->next = tmpcell;
}

/* 插入元素,插入元素到表尾*/
void AddEnd(List L, Elemtype elem)
{
    Position tmpcell,h;

    /* 分配一个节点内存*/
    if (!(tmpcell = (struct node *)malloc(sizeof(struct node))))
    {
        printf("节点内存分配失败啦
");
        return ;
    }
    tmpcell->elem = elem;
    tmpcell->next = NULL;
    
    /* 如果是空表*/
    if (L->next == NULL)
    {
        L->next = tmpcell;
        return;
    }

    /* 如果不是空表*/
    /* 移动节点指针,让它指向最后一个节点位置*/
    h = L->next;
    while (h != NULL && h->next != NULL)
        h = h->next;

    /* 自己犯得错误写法, 注解一下嘿嘿,导致了h是控制空指针*/
    /* 刚开始h到这个地方的时候是空指针,所以下面的写法是错误滴,现在修改好了呀*/
    h->next = tmpcell;
}


/* 返回特定的数据在表中位置*/
/* 1. 如果遍历完后,没有发现这个指针,返回的应该是链表的最后一个元素,应该是NULL*/
/* 2. 这个算法实现参考自 数据结构与算法分析:c语言描述*/
Position Find(List L, char *key)
{
    Position p;

    p = L->next;
    while (p != NULL && !(strcmp(p->elem.key,key) == 0))
        p = p->next;

    return p;
}

/* 如果key找到, 则返回key对应的前一个节点*/
Position FindPrevious(List L, char *key)
{
    Position p;
    p = L;

    if (L->next->next == NULL)
        return NULL;

    while (p->next != NULL && !(strcmp(p->next->elem.key,key) == 0))
        p = p->next;
    return p;
}

/*在特定结点的后面插入新的结点*/
int Insert(List L, Elemtype elem, char *key)
{
    Position p, tmpcell;

    if (!(tmpcell = (struct node *)malloc(sizeof(struct node))))
    {
        printf("节点内存分配失败啦
");
        return 0;
    }
    
    p = Find(L,key);
    if (p)
    {
        tmpcell->elem = elem;
        tmpcell->next = p->next;
        p->next = tmpcell;
    }
    else
    {
        free(tmpcell);
        printf("插入节点失败
");
    }
    return 1;
}

/*删除表中某个特定元素*/
int Delete(List L, char *key)
{
    Position p,tmpcell;

    p = Find(L,key);

    if (!IsLast(L,p))
    {
        tmpcell = p->next;  
        p->next = p->next->next;
        free(tmpcell);
    }
    return 1;
}
 
/* 销毁表*/
void DeleteList(List L)
{
    Position p,tmpcell;

    p = L->next;
    L->next = NULL;

    while (p->next != NULL)
    {
        tmpcell = p->next;
        free(p);
        p = tmpcell;
    }
}

/*获取链表的长度*/
int Length(List L)
{
    int i = 0;
    Position p;
    
    p = L->next;

    while (p != NULL)
    {
        i++;
        p = p->next;
    }
    return i;
}

/* 遍历*/
void traverse(List L)
{    
    Position p;
    p = L->next;

    if (L->next== NULL)
        return;

    printf("
当前单链表中所有的存储的数据为:
");

    while(p!= NULL)
    {
        /*在这个地方第一次写成了L,并导致失败!*/
        printf("%s  %s  %d  
",p->elem.key,p->elem.name,p->elem.age);
        p = p->next;
    }
}

最后测试,也是最破烦的, 由于半路出家,  不太会, 由着自己写啦

#include <stdio.h>
#include <string.h>

#include "LinkList.h"


int main()
{
    
    Elemtype elem;
    List L;
    Position p;
    char buf[15]; //key

    int len;

    /*1. 第一种初始化*/
    /*2. 不过这种不建议实用*/
    //L = InitList(L);

    /*拾遗. 1. 如果指针没有初始化,那么L==0xcccccccc*/
    /*拾遗. 2. 想要修改或者是保存某个实参变量的值,那么就应该传递指向这个实参变量的指针*/
    /*2. 第二种初始化方式*/
    InitList(&L);    

    printf("请输入 关键词 姓名 年龄(关键词输入0 ,则退出)
");
    
    /*插入一些数据到表中*/
    do 
    {
        printf("请输入关键词
");
        fflush(stdin);
        scanf("%s",elem.key);
        if (strcmp(elem.key,"0")==0)    
            break;
        scanf("%s%d",elem.name,&elem.age);
        //AddFirst(L,elem);//测试通过
        AddEnd(L,elem);
    } while (1);
    

//     /* 测试在表头进行插入*/
//     fflush(stdin);
//     scanf("%s",elem.key);
//     scanf("%s%d",elem.name,&elem.age);
//     AddFirst(L,elem);

//     /* 测试查找给定关键词所对应的节点*/
//     p = Find(L, "chen");
//     if (p)
//         printf("
%s  %s  %d",p->elem.key, p->elem.name, p->elem.age);

//     /* 测试查找给定关键词所对应的前一个节点*/
//     p = FindPrevious(L, "chen");
//     if (p)
//         printf("
%s  %s  %d",p->elem.key, p->elem.name, p->elem.age);

//     /* 测试插入元素*/
//     printf("
请输入插入的关键词位置啦");
//     fflush(stdin);    
//     scanf("%s",buf);
//     printf("
请输入插入的元素!!!
");
//     fflush(stdin);
//     scanf("%s",elem.key);
//     scanf("%s%d",elem.name,&elem.age);
//     Insert(L,elem, buf);


//     /* 测试表是否为空*/
//     if (IsEmpty(L))
//         printf(">>>>>>>>>>>>>>>>>>>>>>是空表!
");
//     else
//         printf(">>>>>>>>>>>>>>>>>>>>>>表中含有数据!
");
     

//     /* 测试删除指定位置的元素*/
//     printf("
请输入删除的关键词位置啦
");
//     fflush(stdin);
//     scanf("%s",buf);
//     Delete(L,buf);

//     /* 测试取得链表的长度*/
//     len = Length(L);
//     printf("
%d",len);

//     traverse(L);    
//     DeleteList(L);    

    traverse(L);
    free(L);
    return 0;
}
原文地址:https://www.cnblogs.com/dLong/p/3371344.html