| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 10243 人关注过本帖, 1 人收藏
标题:分享:通用链表(有任何问题或建议,请提出)(5.2新增两个函数)
只看楼主 加入收藏
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 19楼 xzlxzlxzl
你说的main()函数的问题,那个只是调用。
我想你的迷惑,并不是因为List,而是估计你还没弄明白多文件。
你完全可以理解成库函数,比如#include <stdio.h>
stdio.h中定义了几个结构,一个是FILE,只要你调用了stdio.h,你就可以声明FILE类型的变量,对吧?
在这里也是相同的道理。

[此贴子已经被作者于2017-4-27 21:39编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-27 21:25
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 19楼 xzlxzlxzl
我只是改了测试用的main()函数,毕竟用另一个结构来测试不限制类型在打印方面有点不好看,改成int类型,看起来比较好看。
主要是为了测试First() 和DelFirst()两个新函数。

用int类型,可以在一排打印,比较容易、清晰的看到变化。

[此贴子已经被作者于2017-4-27 21:28编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-27 21:26
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 19楼 xzlxzlxzl
实现文件和main()函数同时编译。

在main()函数中 #include 接口。

我的这个还比较初级,我还没学会编译成动态链接或静态链接,那样的话,使用起来就跟标准库函数一样了,只需要#include 头文件,不再需要同时编译实现文件。

我举例说明一下:

这里有3个文件,1个是GenericityList.h,一个是GenericityList.c, 一个是ceshi2.c(也就是那个测试)
用gcc是这样编译的
gcc -Wall ceshi2.c GenericityList.c -o ceshi2

用VS的话,你需要建立3个源文件,一个是ceshi2.c,一个是GenericityList.c,一个GenericityList.h,然后点击生成就可以了。

注意一点,ceshi2.c 和 List.c 文件中,必须#include "List.h",否则无法使用这些链表函数,也不能声明List类型的变量。

[此贴子已经被作者于2017-4-27 21:47编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-27 21:30
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
大概是我对“通用”和“标准”的理解有误。
FILE*的结构作为文件输入输出已经被C基本函数库标准化了,学习任何语言的、写操作系统的,只要涉及文件操作,就明的或暗地遵循这个标准;而通用则是反着来的,要求不管用户给什么数据,函数都能实现相应功能,比如,我的函数功能是做粉的,用户给面,我就做面粉,用户给米,我就做米粉。因此,我理解的是“标准”是写函数要遵循的,“通用”则是写函数要适应的。
另:“typedef struct List *List”在vs2010里的错误提示是:error C2040: “List”:“List *”与“List”的间接寻址级别不同。

[此贴子已经被作者于2017-4-27 21:50编辑过]

2017-04-27 21:47
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 24楼 xzlxzlxzl
你#include "GenericityList.h"了吗?如果这样写的话,你必须把GenericityList.h 和GenericityList.c 放在你的项目的同目录下。
当然你也可以#include "x:\....\GenericityList.h",这样就不需要放在项目的同目录下了。

你稍微等等,我打开Vs2015,建立一个项目,截图给你。

我说stdio.h这个,只是一个例子,只是告诉你,应该这样使用。
stdio.h的实现文件是动态链接的,所以你不需要同时编译它的实现文件。


[此贴子已经被作者于2017-4-27 21:51编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-27 21:48
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
图片附件: 游客没有浏览图片的权限,请 登录注册


好久不用VS2015了,都不会用了。

添加——现有项,选择GenerictyList.h 和 GenericityList.c 就可以了。


[此贴子已经被作者于2017-4-27 21:59编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-27 21:58
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
Vs2015跟我的GCC应该冲突了,我看不到代码,但是编译却是可以。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-27 22:02
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
    Root = MakeEmpty( Root );

记得删除main()函数中的这一句,MakeEmpty()这个函数已经被我删除了,这个函数还不够完善。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-27 22:07
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
图片附件: 游客没有浏览图片的权限,请 登录注册


我用VS2015编译,0警告,0错误的。

[此贴子已经被作者于2017-4-27 22:20编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-27 22:17
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
忙了许久~才弄好插入尾部节点~还有很多功能没有完善~(有些函数还没有测试~可能有bug)~嘿嘿~不过这个可以当作栈和队列通用的双向链表了~~~

程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>

#ifndef _STRUCTURE_LIST_
#define _STRUCTURE_LIST_

#define LEN_ListNode sizeof(ListNode)
#define LEN_List sizeof(List)

typedef struct ListNode
{
    void* Element;            //目录
    struct ListNode* next;    //双向链表
    struct ListNode* prior;
}ListNode,*PListNode;

typedef struct List      //链表信息
{
    PListNode front;
    PListNode rear;

    size_t size;       //统计容量
    int length;        //统计链表长度
    int Add;           //存放结构体成员的地址

}List,*PList;


void Creat_Link(PList* p,void* Add,size_t size);                      //初始化一个链表
void Creat_Node(PListNode* p,void* Value,size_t size);                //创建一个节点

int Insert_Node(PListNode p1,PListNode p2);  //插入一个头节点
int Insert_Rear(PList p1,void* p2);                  //尾插
int Insert_Front(PList p1,void* p2);                 //头插

PListNode Find_Front(PList p,void* member,int k,void* Temp,int (*COM)(const void* p1,const void* p2));  //查找信息并返回该节点
PListNode Find_Node(PList p,PListNode pt,void* member,int k,void* Temp,int (*COM)(const void* p1,const void* p2));  //在当前节点开始查找

void Print_Node(void* p,void (*COM)(void* p));      //输出节点
int Print_List(PList p,void (*COM)(void* p));      //输出链表(不带换行符)
int Println_List(PList p,void (*COM)(void* p));    //输出链表(带换行符)
int RePrint_List(PList p,void (*COM)(void* p));    //逆向输出链表(不带换行符)
int RePrintln_List(PList p,void (*COM)(void* p));  //逆向输出链表(带换行符)

int Del_Node(PListNode* p);                        //删除一个节点

int Del_Node_ReNext(PList p,PListNode* pt);                 //删除一个节点并返回后一个节点
int Del_Node_RePrior(PList p,PListNode* pt);                //删除一个节点并返回前一个节点

int Del_ListLink(PList* p);                        //删除头节点和尾节点 
int Del_List(PList* p,int k);                       //清空链表(k=0则表示保留头尾节点,k=1则表示不保留头尾节点)

int Del_Rear(PList p,void* Value);                             //删除尾部数据并读取(NULL表示不读取数据)
int Del_Front(PList p,void* Value);                            //删除头部数据并读取(NULL表示不读取数据)

int Remove_Rear(PList p,void* Value);                         //读取尾部数据并删除
int Remove_Front(PList p,void* Value);                        //读取头部数据并删除

void* Get_Data(void* p1,void* p2,size_t size);           //读取节点数据

void* Get_Data_By_Rear(PList p,void* Value);          //在链表中读取尾节点数据
void* Get_Data_By_Front(PList p,void* Value);         //在链表中读取头节点数据

void Reverse(PList p);                              //链表逆转

void Link_Sort_Auto(PList p,void* member,size_t size,int(*COM)(const void* p1,const void* p2));   //链表排序(自动快排)
void Link_Sort_NonAuto(PList p,int(*COM)(const void* p1,const void* p2));                         //手动排序(自己写自定义函数)

int Copy_List(PList p1,PList p2);                                 //复制一个链表(如果另外一个链表为非空则把数据添加至末尾)
int Empty_List(PList p);                                          //判断链表是否为空

int Comp_Int(const void* a,const void* b);                         //比较INT型数据
int Comp_Float(const void* a,const void* b);                       //比较Float型数据
int Comp_Double(const void* a,const void* b);                      //比较Doulbe型数据
int Comp_Char(const void* a,const void* b);                        //比较Char型数据
int Comp_String(const void* a,const void* b);                      //比较字符串类数据

typedef struct List_FUN
{
    void (*Creat_Link)(PList* p,void* Add,size_t size);                      //初始化一个链表
    void (*Creat_Node)(PListNode* p,void* Value,size_t size);                //创建一个节点

    int (*Insert_Node)(PListNode p1,PListNode p2);          //插入一个节点
    int (*Insert_Rear)(PList p1,void* p2);                  //尾插
    int (*Insert_Front)(PList p1,void* p2);                 //头插

    PListNode (*Find_Front)(PList p,void* member,int k,void* Temp,int (*COM)(const void* p1,const void* p2));  //查找信息并返回该节点
    PListNode (*Find_Node)(PList p,PListNode pt,void* member,int k,void* Temp,int (*COM)(const void* p1,const void* p2));//在当前节点开始查找

    void (*Print_Node)(void* p,void (*COM)(void* p));        //输出节点
    int (*Print_List)(PList p,void (*COM)(void* p));        //输出链表(不带换行符)
    int (*Println_List)(PList p,void (*COM)(void* p));      //输出链表(带换行符)
    int (*RePrint_List)(PList p,void (*COM)(void* p));      //逆向输出链表(不带换行符)
    int (*RePrintln_List)(PList p,void (*COM)(void* p));    //逆向输出链表(带换行符)

    int (*Del_Rear)(PList p,void* Value);                   //删除尾部数据并读取(NULL表示不读取数据)
    int (*Del_Front)(PList p,void* Value);                   //删除头部数据并读取(NULL表示不读取数据)

    int (*Del_NodeReNext)(PList p,PListNode* pt);                    //删除一个节点并返回后一个节点
    int (*Del_Node_RePrior)(PList p,PListNode* pt);                  //删除一个节点并返回前一个节点

    int (*Remove_Rear)(PList p,void* Value);                 //读取尾部数据并删除
    int (*Remove_Front)(PList p,void* Value);                //读取头部数据并删除

    int (*Del_List)(PList* p,int k);                         //清空链表(k=0则表示保留头尾节点,k=1则表示不保留头尾节点)

    void* (*Get_Data)(void* p1,void* p2,size_t size);         //读取节点数据

    void* (*Get_Data_By_Rear)(PList p,void* Value);          //在链表中读取尾节点数据
    void* (*Get_Data_By_Front)(PList p,void* Value);         //在链表中读取头节点数据

    void (*Reverse)(PList p);                               //链表逆转

    void (*Link_Sort_Auto)(PList p,void* member,size_t size,int (*COM)(const void* p1,const void* p2));   //链表排序(自动快排)
    void (*Link_Sort_NonAuto)(PList p,int(*COM)(const void* p1,const void* p2));                          //手动排序(自己写自定义函数)

    int (*Copy_List)(PList p1,PList p2);                               //复制一个链表(如果另外一个链表为非空则把数据添加至末尾)
    int (*Empty_List)(PList p);                                          //判断链表是否为空

    int (*Comp_Int)(const void* a,const void* b);                      //比较INT型数据
    int (*Comp_Float)(const void* a,const void* b);                    //比较Float型数据
    int (*Comp_Double)(const void* a,const void* b);                   //比较Doulbe型数据
    int (*Comp_Char)(const void* a,const void* b);                     //比较Char型数据
    int (*Comp_String)(const void* a,const void* b);                   //比较字符串类数据

}List_Function;


List_Function List_Fun=
{
    Creat_Link,
    Creat_Node,

    Insert_Node,
    Insert_Rear,
    Insert_Front,

    Find_Front, 
    Find_Node,

    Print_Node,
    Print_List,
    Println_List,
    RePrint_List,
    RePrintln_List,

    Del_Rear,
    Del_Front,

    Del_Node_ReNext,
    Del_Node_RePrior,

    Remove_Rear,
    Remove_Front,

    Del_List,

    Get_Data,

    Get_Data_By_Rear,         
    Get_Data_By_Front,

    Reverse,

    Link_Sort_Auto,
    Link_Sort_NonAuto,

    Copy_List,
    Empty_List,

    Comp_Int,
    Comp_Float,
    Comp_Double,
    Comp_Char,
    Comp_String,
};

void Creat_Link(PList* p,void* Add,size_t size)
{
    assert(*p=(PList)malloc(LEN_List));

    memset(*p,0,LEN_List);
    (*p)->Add=(int)Add;           //初始化链表地址值
    (*p)->size=size;             //初始化链表容量

    assert((*p)->front=(*p)->rear=(PListNode)malloc(LEN_ListNode));
    memset((*p)->front,0,LEN_ListNode);

    assert((*p)->front->next=(*p)->rear=(*p)->rear->next=(PListNode)malloc(LEN_ListNode));
    memset((*p)->rear,0,LEN_ListNode);

    (*p)->rear->prior=(*p)->front;   

}
void Creat_Node(PListNode* p,void* Value,size_t size)      //创建一个节点和和目录分配空间
{
    assert((*p)=(PListNode)malloc(LEN_ListNode));
    memset(*p,0,LEN_ListNode);

    assert((*p)->Element=malloc(size));
    memset((*p)->Element,0,size);

    if (Value!=NULL)
        memmove((*p)->Element,Value,size);
} 

int Insert_Node(PListNode p1,PListNode p2)
{
    if (p1==NULL)
        return 0;   //插入失败则返回0

    p2->next=p1->next;
    p2->prior=p1;

    p1->next=p2;

    if (p2->next)
        p2->next->prior=p2;


    return 1;    //插入成果返回1
}

int Insert_Rear(PList p1,void* p2)          //尾插
{
    PListNode t=NULL;

    if (p1==NULL)
        return 0;

    Creat_Node(&t,p2,p1->size);

    if (Insert_Node(p1->rear->prior,t))
    {
        ++p1->length;
        return 1;
    }

    Del_Node(&t);

    return 0;
}

int Insert_Front(PList p1,void* p2)         //头插
{
    PListNode t=NULL;

    if (p1==NULL)
        return 0;

    Creat_Node(&t,p2,p1->size);

    if (Insert_Node(p1->front,t))
    {
        ++p1->length;
        return 1;
    }

    Del_Node(&t);

    return 0;
}

void Print_Node(void* p,void (*COM)(void* p))  //输出节点
{
    if (p==NULL)
        return ;

    (*COM)(p);
}

int Print_List(PList p,void (*COM)(void* p))  //输出链表
{
    PListNode t=NULL;
    if (p==NULL)
        return -1;

    if (p->front==NULL||p->rear==NULL)
        return 0;

    t=p->front->next;

    while (t!=p->rear)
    {
        Print_Node(t->Element,COM);
        t=t->next;
    }

    return 1;
}

int Println_List(PList p,void (*COM)(void* p))  //输出链表
{
    int k=Print_List(p,COM);

    puts("");

    return k;
}

int RePrint_List(PList p,void (*COM)(void* p))
{
    PListNode t=NULL;
    if (p==NULL)
        return -1;

    if (p->front==NULL||p->rear==NULL)
        return 0;

    t=p->rear->prior;

    while (t!=p->front)
    {
        Print_Node(t->Element,COM);
        t=t->prior;
    }

    return 1;
}

int RePrintln_List(PList p,void (*COM)(void* p))  //逆向输出链表(带换行符)
{
    int k=RePrint_List(p,COM);

    puts("");

    return k;
}

void* Get_Data(void* p1,void* p2,size_t size)           //读取节点数据
{
    if (p2==NULL)
        return NULL;

    if (p1!=NULL)
        memmove(p1,p2,size);

    return p2;
}

int Del_Node(PListNode* p)                        //删除一个节点
{
    if (*p==NULL)
        return -1;

    if ((*p)->Element==NULL)
        return 0;

    free((*p)->Element);
    (*p)->Element=NULL;

    free(*p);
    *p=NULL;

    return 1;
}

int Del_Node_ReNext(PList p,PListNode* pt)         //删除一个节点并返回后一个节点
{
    PListNode t=NULL;

    if (p==NULL||p->length==0)
        return 0;

    t=(*pt)->next;
    (*pt)->prior->next=(*pt)->next;
    (*pt)->next->prior=(*pt)->prior;


     if (Del_Node(pt))
     {
         --p->length;
         *pt=t;
     }
    
    return 1;
}

int Del_Node_RePrior(PList p,PListNode* pt)         //删除一个节点并返回前一个节点
{
    PListNode t=NULL;

    if (p==NULL||p->length==0)
        return 0;

    t=(*pt)->prior;
    (*pt)->prior->next=(*pt)->next;
    (*pt)->next->prior=(*pt)->prior;

     if (Del_Node(pt))
     {
         --p->length;
         *pt=t;
     }

    return 1;
}

int Del_ListLink(PList* p)                        //删除头节点和尾节点
{
    if (*p==NULL)
        return 0;

    if ((*p)->front)
    {
        free((*p)->front);
        (*p)->front=NULL;
    }
    else
        return 0;

    if ((*p)->rear)
    {
        free((*p)->rear);
        (*p)->rear=NULL;
    }
    else
        return 0;

    free(*p);
    *p=NULL;

    return 1;
}

int Del_Rear(PList p,void* Value)                           //删除尾部数据
{
    PListNode t=NULL;

    if (p==NULL||p->length==0)
        return 0;

    t=p->rear->prior;
    t->prior->next=t->next;
    t->next->prior=t->prior;

    if (Del_Node(&t))
        --p->length;

    if (Value==NULL)
        return 1;

    if (p->rear->prior->Element!=NULL)
        Get_Data(Value,p->rear->prior->Element,p->size);

    return 1;
}

int Del_Front(PList p,void* Value)                         //删除头部数据
{
    PListNode t=NULL;

    if (p==NULL||p->length==0)
        return 0;

    t=p->front->next;
    t->prior->next=t->next;
    t->next->prior=t->prior;

    if (Del_Node(&t))
        --p->length;

    if (Value==NULL)
        return 1;

    if (p->front->next->Element!=NULL)
        Get_Data(Value,p->front->next->Element,p->size);

    return 1;
}

int Remove_Rear(PList p,void* Value)                         //读取尾部数据并删除
{
     if (p==NULL||p->length==0)
        return 0;

     if (Value!=NULL)
        memmove(Value,p->rear->prior->Element,p->size);

    return Del_Rear(p,NULL);
}
int Remove_Front(PList p,void* Value)                        //读取头部数据并删除
{
    if (p==NULL||p->length==0)
        return 0;

    if (Value!=NULL)
        memmove(Value,p->front->next->Element,p->size);

    return Del_Front(p,NULL);
}

int Del_List(PList* p,int k)                       //清空链表(k=0则表示保留头尾节点,k=1则表示不保留头尾节点)
{
    if (k==0&&Del_Front(*p,NULL)==0)
        return 0;

    while (Del_Front(*p,NULL));

    if (k)
        return Del_ListLink(p);

    return 1;
}

PListNode Find_Node(PList p,PListNode pt,void* member,int k,void* Temp,int (*COM)(const void* p1,const void* p2))  //在当前节点开始查找
{
    PListNode t=pt;
    if (t==NULL)
        return NULL;

    while (t->next!=NULL)
    {
        if (t->Element!=NULL&&(*COM)((const void* )((int)(t->Element)+((int)member-p->Add)),(const void*)member)==k)
            break;

        t=t->next;
    }

    if (t->Element!=NULL&&Temp!=NULL)
    {
        Get_Data(Temp,t->Element,p->size);
        return t;
    }
    else if (t->next!=NULL)
        return t;

    return NULL;
}

PListNode Find_Front(PList p,void* member,int k,void* Temp,int (*COM)(const void* p1,const void* p2))   //查找信息并返回该节点
{
    if (p==NULL||p->front->next==p->rear)
        return NULL;

    return Find_Node(p,p->front->next,member,k,Temp,COM);
}

void* Get_Data_By_Rear(PList p,void* Value)          //获取表尾数据
{
    if (p==NULL||p->front->next==p->rear)
        return NULL;

    return Get_Data(Value,p->rear->prior->Element,p->size);
}

void* Get_Data_By_Front(PList p,void* Value)          //获取表头数据
{
    if (p==NULL||p->front->next==p->rear)
        return 0;

    return Get_Data(Value,p->front->next->Element,p->size);
}

void Reverse(PList p)                              //链表逆转
{
    PListNode p1=NULL;
    PListNode p2=NULL;
    PListNode pt=NULL;

    if (p==NULL)
        return ;

    p1=p->front;
    p2=p1;
    pt=p1;

    if (p->length==0)
        return ;

    while (p2=p2->next)
    {
        p1->next=p1->prior;
        p1=p1->prior=p2;
    }

    p1->next=p1->prior;
    p1->prior=NULL;

    p->front=p1;
    p->rear=pt;
}

int Empty_List(PList p)                                          //判断链表是否为空
{
    if (p==NULL)
        return 0;

    return p->length==0;
}

void Link_Sort_Auto(PList p,void* member,size_t size,int (*COM)(const void* p1,const void* p2))   //自动快排
{
    size_t T_size=p->size*(p->length);   
    int length=p->length;

    char* Temp=(char* )malloc(T_size);         //创建排序缓冲区
    char* PTemp=Temp;

    int i=0;

    size_t size1=(int )member-p->Add;
    size_t size2=size;
    size_t size3=p->size-size1-size2;


    assert(Temp);
    memset(Temp,0,T_size);
         

    while (p->length!=0)               //拷贝数据到缓冲区
    {
           memmove(PTemp,(void* )((int )p->front->next->Element+size1),size2);
        PTemp+=size2;

        memmove(PTemp,(void* )((int )p->front->next->Element),size1);
        PTemp+=size1;

        memmove(PTemp,(void* )((int )p->front->next->Element+size1+size2),size3);
        PTemp+=size3;

        Del_Front(p,PTemp);
    }
    
    qsort(Temp,length,p->size,COM);  //快排

    for (i=0,PTemp=Temp;i!=length;++i)   //把快排后的数据写回链表
    {
        Insert_Rear(p,NULL);

        memmove(p->rear->prior->Element,PTemp+size2,size1);
        memmove((void* )((int )p->rear->prior->Element+size1),PTemp,size2);
        memmove((void* )((int )p->rear->prior->Element+size1+size2),PTemp+size1+size2,size3);
        PTemp+=p->size;

    }

    PTemp=NULL;

    free(Temp);

    Temp=NULL;
}

void Link_Sort_NonAuto(PList p,int(*COM)(const void* p1,const void* p2))                         //手动排序(自己写自定义函数)
{
    size_t T_size=p->size*(p->length);   
    int length=p->length;

    char* Temp=(char* )malloc(T_size);         //创建排序缓冲区
    char* PTemp=Temp;

    int i=0;

    assert(Temp!=NULL);
    memset(Temp,0,T_size);

    Get_Data_By_Front(p,PTemp);
    while (p->length!=0)
        Del_Front(p,PTemp+=p->size);

    qsort(Temp,length,p->size,COM);

    for (i=0,PTemp=Temp;i!=length;++i)   //把快排后的数据写回链表
    {
        Insert_Rear(p,PTemp);
        PTemp+=p->size;
    }

    PTemp=NULL;

    free(Temp);
    Temp=NULL;
}

int Copy_List(PList p1,PList p2)
{
    PListNode pt=NULL;
    int i=p2->length;

    if (p1==NULL||p2==NULL)
        return 0;


    pt=p2->front->next;

    while (i--)
    {
        Insert_Rear(p1,pt->Element);
        pt=pt->next;
    }

    return 1;
}

int Comp_Int(const void* a,const void* b)                        //比较INT型数据
{
    int ta=*(int* )a;
    int tb=*(int* )b;

    if (ta<tb)
        return -1;

    if (ta>tb)
        return 1;

    return 0;
}
int Comp_Float(const void* a,const void* b)                     //比较Float型数据
{
    float ta=*(float* )a;
    float tb=*(float* )b;

    if (ta<tb)
        return -1;

    if (ta>tb)
        return 1;

    return 0;
}
int Comp_Double(const void* a,const void* b)                   //比较Doulbe型数据
{
    double ta=*(double* )a;
    double tb=*(double* )b;

    if (ta<tb)
        return -1;

    if (ta>tb)
        return 1;

    return 0;
}
int Comp_Char(const void* a,const void* b)                     //比较Char型数据
{
    char ta=*(char* )a;
    char tb=*(char* )b;

    if (ta<tb)
        return -1;

    if (ta>tb)
        return 1;

    return 0;
}
int Comp_String(const void* a,const void* b)                  //比较字符串类数据
{
    int t=strcmp((char* )a,(char* )b);

    if (t<0)
        return -1;

    if (t>0)
        return 1;

    return 0;
}

#endif





程序代码:
#include"List.h"
#include<time.h>

typedef struct Node
{
    int a;
    char b;
    double c;
    
}Node,*PNode;

Node node={0};
Node t_node={0};

void Print_COM(void* p);
int COM(const void* pa,const void* pb);

int main()
{
    PList p=NULL;
    PList p2=NULL;
    PListNode pp=NULL;
    PNode pn=NULL;

    int i=0;

    srand((unsigned )time(NULL));

    List_Fun.Creat_Link(&p,&node,sizeof(Node));

    puts("尾插");
    for (i=0;i<5;++i)
    {
         node.a=rand()%100;
         node.b=rand()%26+'a';
         node.c=rand()/16383.0;
         List_Fun.Insert_Rear(p,&node);   //尾插
    }

    List_Fun.Println_List(p,Print_COM);   //输出链表

    puts("逆序输出");
    List_Fun.RePrintln_List(p,Print_COM); //逆序输出

    puts("头插");
    for (i=5;i<10;++i)
    {
         node.a=i;
         node.b='a'+i;
         node.c=rand()/16383.0;
         List_Fun.Insert_Front(p,&node);  //头插
    }

    List_Fun.Println_List(p,Print_COM);  

    puts("逆序输出");
    List_Fun.RePrintln_List(p,Print_COM);

    puts("尾删");
    List_Fun.Del_Rear(p,NULL);   //尾删
    List_Fun.Del_Rear(p,NULL);

    List_Fun.Println_List(p,Print_COM);

    puts("头删");
    List_Fun.Del_Front(p,NULL);   //头删
    List_Fun.Del_Front(p,NULL);

    List_Fun.Println_List(p,Print_COM);

    node.a=5;
    printf("从头节点开始查找元素%d\n",node.a);

    pp=List_Fun.Find_Front(p,&node.a,0,&t_node,List_);   //从头节点开始查找
    if (pp!=NULL)
    {
        printf("%d %c %.2f\n",((PNode)pp->Element)->a,((PNode)pp->Element)->b,((PNode)pp->Element)->c);
        printf("%d %c %.2f\n\n",t_node.a,t_node.b,t_node.c);
    }

    pp=p->front->next->next;

    node.b='g';
    printf("从头节点开始查找元素%c\n",node.b);

    pp=List_Fun.Find_Front(p,&node.b,0,&t_node,List_);
    if (pp!=NULL)
    {
        printf("%d %c %.2f\n",((PNode)pp->Element)->a,((PNode)pp->Element)->b,((PNode)pp->Element)->c);
        printf("%d %c %.2f\n\n",t_node.a,t_node.b,t_node.c);
    }

    node.a=5;
    printf("从当前节点开始查找元素%d\n",node.a);

    pp=List_Fun.Find_Node(p,pp,&node.a,1,&t_node,List_);    //从指定节点开始查找
    if (pp!=NULL)
    {
        printf("%d %c %.2f\n",((PNode)pp->Element)->a,((PNode)pp->Element)->b,((PNode)pp->Element)->c);
        printf("%d %c %.2f\n\n",t_node.a,t_node.b,t_node.c);
    }

    puts("手动快排");
    List_Fun.Link_Sort_NonAuto(p,COM);     //手动快排
    List_Fun.Println_List(p,Print_COM);

    puts("链表逆转");
    List_Fun.Reverse(p);                   //链表逆转

    List_Fun.Println_List(p,Print_COM);

    puts("自动快排");
    Link_Sort_Auto(p,&node.b,sizeof(node.b),List_);  //自动快排
    List_Fun.Println_List(p,Print_COM);

    puts("自动快排");
    Link_Sort_Auto(p,&node.c,sizeof(node.c),List_);  //自动快排
    List_Fun.Println_List(p,Print_COM);

    printf("链表长度为%d\n",p->length);

    puts("复制链表");                                 //复制链表
    List_Fun.Creat_Link(&p2,&node,sizeof(Node));
    List_Fun.Copy_List(p2,p);
    List_Fun.Println_List(p2,Print_COM);


    List_Fun.Del_List(&p,1);   //释放链表
    List_Fun.Del_List(&p2,1);

    return 0;
}

void Print_COM(void* p)
{
    PNode t=(PNode)p;

    printf("%-4d",t->a);
    printf("%-4c",t->b);
    printf("%-.2f",t->c);

    puts("");
}

int COM(const void* pa,const void* pb)
{

    int a=((PNode)pa)->a;
    int b=((PNode)pb)->a;

    if (a>b)
        return 1;

    if (a<b)
        return -1;

    return 0;
}


[此贴子已经被作者于2017-6-4 21:38编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-29 15:12
快速回复:分享:通用链表(有任何问题或建议,请提出)(5.2新增两个函数)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.051501 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved