数据结构-线性表、单链表及双链表

线性表

list.h

//list.h   
    
#ifndef _LIST_H   
#define _LIST_H //条件编译语句   
    
#define LIST_INIT_SIZE  10  //线性表初始大小   
#define LIST_INCREMENT  10  //递增大小   
    
typedef struct  
{   
    ElemType * elem;    //线性表首地址   
    int length;         //线性表当前使用长度   
    int size;           //线性表当前最大长度   
}LIST;   
    
LIST *InitList();       //初始化   
void FreeList(LIST *l);   
int InsertList(LIST* l,int i,ElemType *e);   
int DeleteList(LIST *l,int i);   
    
#endif 

list.c

//list.c   
#include <stdio.h>   
#include<stdlib.h>   
#include "stu.h"   
#include "list.h"   
    
//初始线性表函数   
LIST * InitList()   
{   
    LIST* l=(LIST*)malloc(sizeof(LIST));    
    //在堆中动态定义一个线性表结构指针   
    if(l==NULL)   
    {   
        exit(0);   
    }   
    
    l->elem=(ElemType*)malloc(LIST_INIT_SIZE* sizeof(ElemType));   
    //在堆中动态开辟数据空间   
    if(l->elem==NULL)   
    {   
        free(l);   
        exit(0);   
    }   
    l->length=0;   
    l->size=LIST_INIT_SIZE;   
    return l;   
}   
    
void FreeList(LIST *l)   
{   
    free(l->elem);  //释放线性表的成员空间   
    free(l);    //释放线性表本身   
}   
    
int InsertList(LIST* l,int i,ElemType *e)   
{   
    ElemType *p=NULL,*q=NULL,*newElem=NULL;   
    if(l==NULL||e==NULL)   
        return 0;   
    if(i<1||i>l->length+1)   
        return 0;   
    if(l->length>=l->size)   
    {   
        newElem=realloc(l->elem,   
            (l->size+LIST_INCREMENT)*sizeof(ElemType));   
        if(newElem==NULL)   
            return 0;   
        l->elem=newElem;   
        l->size+=LIST_INCREMENT;   
    }   
    
    q=&l->elem[i-1]; //要插入的位置   
    for(p=&(l->elem[l->length-1]);p>=q;p--)   
        *(p+1)=*p; //将p往后移一位   
    *q=*e; //插入   
    ++l->length;   
    return 1;   
}   
    
int DeleteList(LIST *l,int i)   
{   
    ElemType *p=NULL,*q=NULL;   
    if(l==NULL)   
        return 0;   
    if(i<1||i>l->length)   
        return 0;   
    p=&l->elem[i-1];   
    q=&l->elem[l->length-1];   
    for(;p<q;p++)   
        *p=*(p+1);//将后面的元素向前移   
    --l->length;   
    return 1;   
} 

stu.h

//stu.h   
    
#ifndef _STU_H   
#define _STU_H   
    
typedef struct  //定义一个学生的结构体   
{   
    char sno[5];   
    char name[21];   
    char sex[3];   
    int score;   
}ElemType;   
    
#endif 

main.c

//main.c   
#include <stdio.h>   
#include "stu.h"   
#include "list.h"   
    
ElemType stu[3]={   
    {"s010","张三","男",80},   
    {"s011","张四","男",81},   
    {"s012","张五","男",82}   
};   
    
void main()   
{   
    //定义一个线性性表指针   
    int i;   
    LIST* list=NULL;   
    list=InitList();    //初始化线性表   
         
    for(i=0;i<3;i++)   
        InsertList(list,1,&stu[i]);   
    DeleteList(list,2);   
    
    FreeList(list);   
} 

单链表

list.h

//list.h   
    
#ifndef _LIST_H   
#define _LIST_H   
    
typedef struct _node   
{   //结点类型定义   
    void *data; //结点的数据域   
    struct _node *next; //结点的指针域   
}NODE;   
    
typedef struct  
{   //链表类型定义   
    NODE * head;//头结点   
    NODE * last;//尾结点   
    int length;//链表长度   
}LIST;   
    
LIST* InitList();   
int AddNode(LIST* l,void *data,int size);   
NODE* FindNodeByKey(LIST *l,void *key,   
                    int (*compare)(void*,void*)/*函数指针*/);   
NODE* FindNode(LIST *l,void *key,   
                    int (*compare)(void*,void*)/*函数指针*/,NODE **pre);   
int DeleteListByKey(LIST* l,void* Key,int (*compare)(void*,void*));   
    
#endif 

list.c

//list.c   
    
#include <stdio.h>   
#include <stdlib.h>   
#include <string.h>   
#include "list.h"   
    
LIST* InitList()   
{   
        LIST* l=(LIST*)malloc(sizeof(LIST)); //创建一个链表   
        if(l==NULL)   
            exit(0);   
        memset(l,0,sizeof(LIST));//将链表清零   
        return l;   
}   
    
int AddNode(LIST* l,void *data,int size) //添加结点   
{   
    //在调试中可以这样看结点的值(struct STU*)l->head->data,(struct STU*)l->last->data   
    NODE *n=NULL;   
    if(l==NULL||data==NULL)   
        return 0;   
    n=(NODE*)malloc(sizeof(NODE)); //创建一个结点   
    if(n==NULL)   
        return 0;   
    n->data=data;   
    n->data=malloc(size);   
    if(n->next=NULL)   
    {   
        free(n);   
        return 0;   
    }   
    memcpy(n->data,data,size);//把数据拷到目标结点中去   
    
    /*//方法一  
    if(l->head==NULL)  
    {  
        l->head=n;  
        l->last=n;  
        l->length=1;  
    }  
    else  
    {  
        l->last->next=n;//挂在尾结点后面  
        l->last=n; //改变尾结点的指向  
        l->length++;  
    }  
    */  
    //方法二   
    if(l->head==NULL)   
        l->head=n;   
    else  
        l->last->next=n;   
    l->last=n;   
    l->length++;   
    return 1;   
}   
    
NODE* FindNodeByKey(LIST *l,void *key,   
                    int (*compare)(void*,void*)/*函数指针*/)   
{   //查找结点   
    NODE *p=NULL;   
    if(l==NULL||key==NULL||compare==NULL)   
        return NULL;   
    p=l->head;//让p指向第一个结点   
    while(p)   
    {   
        if(compare(p->data,key)==1)//如果返回为1说明找到了   
            return p;   
        p=p->next;//否则继续往下找   
    }   
    return NULL;//都没找到,返回空   
}   
    
    
NODE* FindNode(LIST *l,void *key,   
                    int (*compare)(void*,void*)/*函数指针*/,NODE **pre)   
{   //查找结点,并传入前一个结点的参数   
    NODE *p=NULL;   
    if(l==NULL||key==NULL||compare==NULL||pre==NULL)   
        return NULL;   
    p=l->head;//让p指向第一个结点   
    *pre=NULL;   
    while(p)   
    {   
        if(compare(p->data,key)==1)//如果返回为1说明找到了   
            return p;   
        *pre=p;//找到的结点的前一个结点   
        p=p->next;//否则继续往下找   
    }   
    return NULL;//都没找到,返回空   
}   
    
int DeleteListByKey(LIST* l,void* key,int (*compare)(void*,void*))   
{   //删除结点   
    NODE *p=NULL,*q=NULL;   
    p=FindNode(l,key,compare,&q/*前一个结点的地址*/);   
    if(p==NULL)   
        return 0;   
    if(q==NULL)//如果前一个结点为空   
        l->head=p->next;//那么将头指针指向要删除的结点的后一个结点   
    else  
        q->next=p->next;   
    if(p==l->last)   
            l->last=q;   
        free(p->data);   
        free(p);   
        l->length--;   
        return 1;   
}  

main.c

//main.c   
    
#include<string.h>   
#include<stdio.h>   
#include "list.h"   
    
struct STU   
{   
    char sno[5];   
    char name[21];   
    int age;   
    float score;   
}s[3]={   
    {"s001","lin wu",12,90},   
    {"s002","xiao ming",13,91},   
    {"s003","wang wu",11,100}   
};   
    
int CompareByName(void *info,void *key)   
{   
    struct STU* stu=(struct STU*)info;   
    char *name=(char *)key;   
    return strcmp(stu->name,name)==0?1:0;   
}   
    
int CompareBySno(void *info,void *key)   
{   
    struct STU* stu=(struct STU*)info;   
    char *sno=(char *)key;   
    return strcmp(stu->sno,sno)==0?1:0;   
}   
    
void main()   
{   
    int i;   
    NODE *res=NULL;//存放找到的结果   
    char name[]="xiao ming",sno[]="s001";   
    LIST* list=InitList();   
    for(i=0;i<3;i++)   
        AddNode(list,&s[i],sizeof(s[i]));   
    
    res=FindNodeByKey(list,name,CompareByName);   
    if(res==NULL)   
        printf("NOT Find\n");   
    else  
        printf("Find it\n");   
    
    if(DeleteListByKey(list,sno,CompareBySno))   
        printf("delete success\n");   
    //在调试中可以这样看结点的值(struct STU*)list->head->data,(struct STU*)list->last->data   
    else  
        printf("delete fail\n");   
}

双链表

list.h

//list.h   
    
#ifndef _LIST_H   
#define _LIST_H   
    
typedef struct _node   
{   
    void *data;   
    struct _node *pior;   
    struct _node *next;   
}NODE;   
    
typedef struct  
{   
    NODE *head;   
    NODE *last;   
    int length;   
}LIST;   
    
LIST *InitList();   
int InsertNode(LIST *l,void *data,int size);   
int DeletNode(LIST* l,int n);   
void PrintList(LIST *l,int page,int perp,void(*printNode)(void*));   
void ClearList(LIST* l);   
void DestroyList(LIST **l);   
    
    
#endif 

list.c

//list.c   
    
#include <stdio.h>   
#include <stdlib.h>   
#include <string.h>   
#include "list.h"   
    
LIST *InitList()//初始化链表   
{   
    LIST *l=(LIST*)malloc(sizeof(LIST));   
    if(l==NULL) exit(0);   
    l->head=(NODE*)malloc(sizeof(NODE));   
    if(l->head==NULL) exit(0);   
    memset(l->head,0,sizeof(NODE));   
    l->last=(NODE*)malloc(sizeof(NODE));   
    if(l->last==NULL) exit(0);   
    memset(l->last,0,sizeof(NODE));   
    
    //l->head->pior==NULL;   
    l->head->next=l->last;//将头结点的后续指向尾结点   
    l->last->pior=l->head;//将尾结点的前驱指向头结点   
    
    l->length=0;   
    return l;   
}   
    
int InsertNode(LIST *l,void *data,int size) //插入结点   
{   
    NODE *n=NULL; //定义一个空结点   
    if(l==NULL||data==NULL||size<=0)//判断传入的参数是否合法   
        return 0;   
    n=(NODE*)malloc(sizeof(NODE));//为结点分配空间   
    if(n==NULL)    
        return 0;   
    n->data=malloc(size);//为结点的数据域分配空间   
    if(n->data==NULL)   
    {   
        free(n);   
        return 0;   
    }   
    memcpy(n->data,data,size);//将传入的数据拷贝到结点的数据域当中   
    n->next=l->last;        //它的后继指针指向尾结点   
    n->pior=l->last->pior;  //它的前驱指针指向尾结点的前一个   
    
    l->last->pior->next=n;  //把尾结点的前一个的后继指针指向它   
    l->last->pior=n;        //把尾结点前驱指针指向它   
    l->length++;            //链表的长度加1   
    return 1;   
}   
    
int DeletNode(LIST* l,int n) //删除结点   
{   
    NODE *p=NULL;   
    int i=0;   
    if(l==NULL||n<1||n>l->length)//判断传入的参数是否合法   
        return 0;   
    p=l->head->next;//将p指向头结点的下一个   
    while(i<l->length)//查找第n个结点   
    {   
        i++;   
        if(i==n)   
            break;   
        p=p->next;   
    }   
    p->pior->next=p->next;//将p的前一个的后继指针指向p的后一个   
    p->next->pior=p->pior;//将p的后一个的前驱指针指向p的前一个   
    free(p->data);//释放p结点的数据域   
    free(p);//释放p结点   
    l->length--;   
    return 1;   
}   
    
void PrintList(LIST *l,int page,int perP,void(*printNode)(void*))//分布打印链表中的数据   
{   //page为页的编号,perP为每页的结点数   
    int start,end,i;   
    NODE *p=NULL;   
    if(l==NULL||printNode==NULL)//判断传入的参数是否有效   
        return;   
    start=(page-1)*perP+1;//将在某页面第一条要打印的数据所对映的结点所在链表中的位置   
    end=page*perP;//将在某页面最后一条要打印的数据所对映的结点所在链表中的位置   
    p=l->head->next;//将p指向第一个数据结点   
    i=0;   
    while(i<l->length && p->next!=NULL)   
    {   
        i++;   
        if(i==start) break;//定位到某页面的第一条要打印的数据   
        p=p->next;   
    }   
    for(;i<=end && p->next!=NULL;i++)//打印某一页面的数据,直到最后一条   
    {   
        printNode(p->data);   
        p=p->next;   
    }   
}   
    
void ClearList(LIST* l)//清空链表   
{   
    NODE *p=NULL;   
    if(l==NULL)   
        return;   
    /*  
    //方法一  
    while(l->length)  
        DeleteNode(l,1);  
    */  
    
    //方法二   
    while(l->length)   
    {   
        p=l->head->next;//把p指向第一数据结点   
        l->head->next=p->next;//把头结点的前驱指针指向p的下一个(第一个数据结点)   
        p->next->pior=l->head;//把p的下一个的前驱指针指向头结点   
        free(p->data);//释放p指向的结点的数据域   
        free(p);//释放p结点   
        l->length--;//链表长度减1   
    }   
}   
    
void DestroyList(LIST **l)//删除链表   
{   
    LIST *p=*l;   
    //定义一个指向链表l的p指针,并将传入的指向链表的指针变量的值*l,即(*&list)赋给它   
    //这里指向链表的指针变量的值*l是链表的地址   
    if(p==NULL) return;   
    ClearList(p);//清空链表   
    free(p->head);//释放头结点   
    free(p->last);//释放尾结点   
    free(p);//释放指针变量   
    //p=NULL;   
    *l=NULL;//将指向链表的指针的值赋成空值,即将指向已经销毁了的链表的指针指向空值   
} 

main.c

//main.c   
    
#include<stdio.h>   
#include "list.h"   
    
double d[5]={10.23,34.23,54.65,122,35.5};   
    
void PrintData(void *data)//打印数据   
{   
    double *d=(double*)data;   
    printf("d=%lf\n",*d);   
}   
    
void main()   
{   
    int i;   
    LIST *list=InitList();   
    for(i=0;i<5;i++)   
        InsertNode(list,&d[i],sizeof(d[i]));   
    PrintList(list,1,3,PrintData);   
    
    DestroyList(&list);//删除链表   
    //&list 传递指向链表的指针变量地址给DestroyList函数   
    if(list==NULL)   
        printf("list is NULL\n");   
    else  
        printf("list is not NULL\n");   
}

版权所有,转载请注明出处 luowei.github.io.