算法2---链表2---链表任意存储的实现

现在我们要在链表中存储任意类型的数据(也就是说数据所占字节数是在使用链表的时候确定),既然要能存储任意类型的数据,那么我们的链表的节点和链表的定义就要做一些修改了。

下图是节点和链表的定义,data是一个ElemType类型的数据,而ElemType是被我们定义成了一个void *,也就是一个空指针。head和tail都是一个ChainNode类型的指针,作为链表的头结点和尾巴节点,头结点本书的数据域是不存放数据的。Nodesize表示要存储的数据类型的字节大小。

代码实现如下

#ifndef _List_H

typedef void * Elemtype

typedef struct node
{
    Elemtype data;
    struct node *next;
}ChainNode;

typedef struct
{
    ChainNode *head;
    int Nodesize;
    ChainNode *tail;
}List;

List *CreateList(int); //创建链表,传递的参数是链表的大小,返回值为指向链表的指针;

void DestoryList(List *);//销毁链表;

void ClearList(List *);//清空链表;

int ListAppend(List*,...);//追加元素;

int ListInsert(List*,int,...);//插入元素;

int ListDelete(List*,int);//删除第几个元素;

int GetElem(List*,int,Elemtype *);//取得第几个元素的值用第三个参数返回。

ChainNode *GetAddr(List *,int);//取得编号为N的元素所在地址;

int TraverseList(List *,int(*)(Elemtype));//遍历访问,访问某个节点元素用函数处理;

ChainNode * NewChainNode (Elemtype);//得到新链表节点;

int IsEmpty(List*);//链表判空;

#endif

/*===========================*/
List *CreateList(int size)
{
    List *pt = 0;
    Elemtype data = 0;
    pt=(List*)malloc(sizeof(List));//分配空间

    if (!pt)//空间分配失败
    {
        return 0;
    }
    pt->head=NewChainNode(data);//指向节点
    if (!pt->head)//失败,释放空间
    {
        free(pt);
        return 0;
    }

    pt->Nodesize=size;

    pt->tail=pt->head;

    return pt;
}

/*============================*/

void DestoryList(List *plist)
{
    ClearList(plist);
    free(plist->head);
    plist->head=0;

    free(plist);
    plist=0;
}

/*============================*/

int ListAppend(List *plist,...)
{
    ChainNode *newpt=0;
    void *data;
    void *pos;
    pos=&plist+1;

    if (!(plist&&plist->head))
    {
        return 0;
    }

    data=(void*)malloc(plist->Nodesize);
    if (!data)
    {
        return 0;
    }

    memcpy(data,pos,plist->Nodesize);

    newpt = NewChainNode(data);

    if (!newpt)
    {
        return 0;
    }

    plist->tail->next = newpt;
    plist->tail = newpt;

    return 1;
}

/*============================*/

int ListInsert(List *plist,int n,...)
{
    ChainNode *pt=0;
    ChainNode *newpt=0;
    void *data;
    void *pos=&plist+2;
    pt = GetAddr(plist,n-1);//得到指定n位置的前一个地址;
    if (!(pt))//如果没有得到地址,返回0;
    {
        return 0;
    }
    data=(void*)malloc(plist->Nodesize);//给数据分配空间;

    if (!data)
    {
        return 0;
    }
    memcpy(data,pos,plist->Nodesize);
    newpt=NewChainNode(data);
    if (!newpt)
    {
        return 0;
    }

    if (pt->next==plist->tail)
    {
        plist->tail=newpt;
    }

    newpt->next=pt->next;
    pt->newpt;

    return 1;
}

/*============================*/
int GetElem(List *plist,int n,Elemtype *data)
{
    ChainNode *pt=0;

    if (!data)
    {
        return 0;
    }
    pt =GetAddr(plist,n);
    if (!pt)
    {
        return 0;
    }
    memcpy(data,pt->data,plist->Nodesize);

    return 1;
}

/*============================*/
int TraverseList(List *plist,int(*f)(Elemtype) )
{
    ChainNode *pt=0;
    int a =0;

    if (!(plist&&plist->head))
    {
        return 0;
    }
    for (a = 0,pt=plist->head->next;pt;pt=pt->next)
    {
        if (!f((pt->data)))
        {
            return a+1;
        }
        a++;
    }
    return 0;
}

/*============================*/
int ListDelete(List* plist,int n)
{
    ChainNode *pt=0;
    ChainNode *pf=0;
    if (!plist->head->next)
    {
        return 0;
    }
    pt=GetAddr(plist,n-1);

    if (pt->next==plist->tail)
    {
        plisy->tail=pt;
    }
    if (!(pt&&pt->next))
    {
        return 0;
    }
    pf=pt->next;
    pt->next=pt->next->next;

    free(pf->data);
    free(pf);

    return 1;
}
/*============================*/

ChainNode * GetAddr(List * plist,int n)
{
    ChainNode * pt = 0;
    int a = 0; 

    if( n < 0)   return 0; 

    pt = plist->head; 

    while( pt && a < n )
    {
        pt = pt->next;
        a++;
    }
    return pt;
} 

/*============================*/

ChainNode * NewChainNode(ElemType data)
{
    ChainNode * pChain=0;
    pChain = ( ChainNode * )malloc( sizeof(ChainNode) ); 

    if( ! pChain )  return 0; 

    pChain->data=data;
    pChain->next=0; 

    return pChain;
} 
#include "list.h"
/*提供两种数据测试*/
typedef   struct {
     char ch ;
     int id;
     char name[10];
     int r;
} myElemType; 

/*
typedef  char myElemType;
*/ 

myElemType a[20] ={{‘a‘,1,"niei",2},{‘b‘,2,"aini",2},{‘c‘,3,"love",2},{‘d‘,4,"jack",2},{‘e‘,5,"alice",2},{‘f‘,6,"ben",2},{‘g‘,7,"carlo",2},{‘h‘,8,"mason",2}}; 

/*
myElemType a[20]="Hello world!";
*/ 

void showList(List* ); 

int putElem( myElemType *);
void main()
{
    List * mylist;
    int n=0;
    myElemType data;
    myElemType data2; 

    myElemType* pdata;
    mylist = CreateList( sizeof(myElemType) ); 

    if( ! mylist)
    {
        printf("error");
        return;
    }
    for( n = 0 ;n < 8 ;n++)
        ListAppend(mylist ,a[n]); 

    showList( mylist); 

    data.ch = ‘*‘;
    data.id = 8;
    strcpy(data.name , "1223");
    data.r = 2; 

/*  a[0]=‘E‘;
    a[1]=‘r‘;
    a[2]=‘r‘;
    a[3]=‘o‘;
    a[4]=‘r‘;
*/  ListInsert(mylist,1,data);
    showList( mylist); 

/**/    data2.ch = ‘A‘;
    data2.id = 54;
    strcpy(data2.name , "bill");
    data2.r = 4;
    ListInsert(mylist,7,data2);
    showList( mylist); 

    ListDelete(mylist,7);
    showList( mylist); 

    ListDelete(mylist,1);
    showList( mylist); 

    if (GetElem(mylist,5,&data2) )
    /*  printf("[%c %d %s %d] ",data2.ch,data2.id,data2.name,data2.r);*/
        printf("[%c]",data2); 

    ClearList(mylist);
    showList( mylist); 

    DestoryList(mylist);
    mylist = 0; 

    showList( mylist); 

}
/*==================*/
void showList(List* plist)
{
    if( !plist  )
        return;
    TraverseList(plist,(int(*)(void *))putElem);
    printf("\n");
}
/*输出字符*/
/*
int putElem(myElemType *data)
{

    if( ! ( data) )
        return 0;

    printf("%c",*data);
    return 1;
}
*/
/*输出结构体*/
/**/
int putElem(myElemType *data)
{ 

    if( ! ( data) )
        return 0;
    printf("[%c %d %s %d] ",(data)->ch,(data)->id,(data)->name,(data)->r);   

    return 1;
} 
时间: 2024-08-28 08:31:31

算法2---链表2---链表任意存储的实现的相关文章

单链表的链式存储总结

基本数据结构之-单链表的链式存储 链表是一种插和删除元素很便捷的数据结构,原因是它存储的数据在内存中不连续,可以根据需要自己动态开辟. 和数组比较起来主要的缺点就是不能随机访问,如果是单链表,那么要访问一个数据,必须从头开始遍历一次! 对于基本数据结构围绕增删查改等操作,单链表的改可以通过删和增的结合来操作.因此就不用代码来表示了! 任何一个数据结构都有它的基本的数据结构,这儿给出一种用void *代替的写法 基本的数据结构的定义: // 定义指针的结构体 typedef struct _LIN

一步一步写算法(之单向链表)

原文:一步一步写算法(之单向链表) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 有的时候,处于内存中的数据并不是连续的.那么这时候,我们就需要在数据结构中添加一个属性,这个属性会记录下面一个数据的地址.有了这个地址之后,所有的数据就像一条链子一样串起来了,那么这个地址属性就起到了穿线连结的作用. 相比较普通的线性结构,链表结构的优势是什么呢?我们可以总结一下: (1)单个节点创建非常方便,普通的线性内存通常在创建的时候就需要设定数据的

Java数据结构和算法(七)——链表

前面博客我们在讲解数组中,知道数组作为数据存储结构有一定的缺陷.在无序数组中,搜索性能差,在有序数组中,插入效率又很低,而且这两种数组的删除效率都很低,并且数组在创建后,其大小是固定了,设置的过大会造成内存的浪费,过小又不能满足数据量的存储. 本篇博客我们将讲解一种新型的数据结构——链表.我们知道数组是一种通用的数据结构,能用来实现栈.队列等很多数据结构.而链表也是一种使用广泛的通用数据结构,它也可以用来作为实现栈.队列等数据结构的基础,基本上除非需要频繁的通过下标来随机访问各个数据,否则很多使

数据结构与算法之PHP实现链表类(单链表/双链表/循环链表)

链表是由一组节点组成的集合.每个节点都使用一个对象的引用指向它的后继.指向另一个节点的引用叫做链. 链表分为单链表.双链表.循环链表. 一.单链表 插入:链表中插入一个节点的效率很高.向链表中插入一个节点,需要修改它前面的节点(前驱),使其指向新加入的节点,而新加入的节点则指向原来前驱指向的节点(见下图). 由上图可知,B.C之间插入D,三者之间的关系为 current为插入节点的前驱节点 current->next = new              // B节点指向新节点D new->n

数据结构与算法(4)链表(下)

链表(下):如何轻松写出正确的链表代码? 技巧一:理解指针或引用的含义 对指针的理解:将某个变量赋值给指针,实际上就是讲这个变量地址赋值给指针,或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量. 例如:p->next=q.这行代码是说,p结点的next指针存储了q结点的内存地址. p->next=p->next->next.这行代码表示,p结点的next指针存储了p结点的下下一个结点的内存地址. 技巧二:警惕指针丢失和内存泄漏 我们希望在结点a

数据结构与算法学习02:链表

一.链表 链表是一种动态集合,它是由一系列元素组成的一个列表. 数组也可以实现列表这种数据结构,但数组是静态的,而链表是动态. 通常,我们定义一个结点类(或结构体)来表示链表的元素,它由两部分组成:数值域和指针域.数值域存储当前结点的键,指针域存储下一个节点的地址. template <class Type> struct nodeType { Type info; nodeType<Type> *link; }; 链表的一些基本操作如下: 初始化为空表 判断是否为空 打印(遍历)

009实现一个算法来删除单链表中的一个结点,只给出指向那个结点的指针(keep it up)

呵呵,这个题不能直接删除已知的结点,因为是单链表,不知道前驱,只知道 后继结点,直接删除会使链表断开.不过我们可以删除已知结点的后继结点, 把后继结点的值赋值给已知结点. #include <iostream> struct Node { int data; Node* next; }; bool removeNode(Node* vNode) { if (vNode == NULL || vNode->next == NULL) return false; Node* pNext =

实现一个算法从一个单链表中返回倒数第n个元素(keep it up)

我们维护两个指针, 它们之间的距离为n.然后,我将这两个指针同步地在这个单链表上移动,保持它们的距离 为n不变.那么, 当第二个指针指到空时,第一个指针即为所求. #include <iostream> struct Node { int data; Node* next; }; void initList(Node* vNode) { for (int i=0; i < 20; ++i) { Node* TempNode = new Node; TempNode->data =

数据结构之自建算法库——循环双链表

本文针对数据结构基础系列网络课程(2):线性表中第13课时循环链表. 按照"0207将算法变程序"[视频]部分建议的方法,建设自己的专业基础设施算法库. 双链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:cdlinklist.h,包含定义双链表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef CDLINKLIST_H_INCLUDED #define CDLINKLIST_H_INCLUDED //循环双链表基本运算函数 typedef int E