使用单链表实现多项式计算示例

所属分类: 软件编程 / C 语言 阅读数: 107
收藏 0 赞 0 分享

复制代码 代码如下:

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

//比较函数返回值
#define A_EQUAL_B  0
#define A_LARGE_B  1
#define A_LOWER_B -1

//错误返回之集合
#define SUCCESS            0
#define POINT_ARG_IS_NULL -1
#define LINKLIST_IS_NULL  -2
#define NOT_FOUND         -3

typedef struct
{
    int cst_term;//常数项
    int idx_term;//指数
}factor;

typedef factor data_t;
typedef struct linklist
{
 data_t data;
 struct linklist *next;
}linklist;

/*
 *
 * malloc头节点,头节点内的数据是无效的
 *
 */
linklist *creat_lnklst()
{
 linklist *head = (linklist *)malloc(sizeof(linklist));
 head->next = NULL;
 return head;
}

/*
 * pll是插入节点的前一项
 * data是数据
 * 为新节点分配内存,之后插入
 *
 */
int ins_head_lnklst(linklist *pll, const data_t *data)
{
 linklist *newnode = NULL;

 if(NULL == pll || NULL == data)
  return POINT_ARG_IS_NULL;

 newnode = (linklist *)malloc(sizeof(linklist));

 newnode->data = *data;

 newnode->next = pll->next;
 pll->next = newnode;

 return SUCCESS;
}

/*
 *
 * pll是要删除节点的前一个
 * data存放删除的数据
 * 检查pll是否是空
 * 检查链表是否为空
 * data是NULL就不用保存删除的数据
 *
 */
int del_head_lnklst(linklist *pll, data_t *data)
{
 linklist *tmp = NULL;

 if(NULL == pll)
  return POINT_ARG_IS_NULL;

 if(pll->next == NULL)
  return LINKLIST_IS_NULL;

 tmp = pll->next;

 if(NULL != data)
  *data = tmp->data;

 pll->next = tmp->next;

 free(tmp);

 return SUCCESS;
}

/*
 *
 * 内部支持data_t大小比较函数
 * 如果data_t修改成其他类型则需要修改此方法
 *
 */
static int cmp_data(const data_t *a, const data_t *b)
{
 int res = 0;

 if(a == NULL || b == NULL)
  return POINT_ARG_IS_NULL;

 res = a->idx_term - b->idx_term;
 if(res == 0)
  return A_EQUAL_B;
 else if(res > 0)
  return A_LARGE_B;
 else
  return A_LOWER_B;
}

/*
 *
 * 实现在链表中查找data匹配的前一项
 * compare是实现虚拟数据类型比较函数
 *
 */
linklist * locate_lnklst(linklist *pll, const data_t *data, int (*compare)(const data_t *, const data_t *))
{
 if(NULL == pll || data == NULL)
  return NULL;

 if(NULL == compare)
  compare = cmp_data;

 while(pll->next)
 {
  if(A_EQUAL_B == compare(&(pll->next->data), data))
   return pll;
  pll = pll->next;
 }

 return NULL;
}

/*
 *
 * 打印链表数据
 * 检查参数空指针
 * 检查空链表
 *
 */
int print_lnklst(linklist *pll)
{
 if(NULL == pll)
  return POINT_ARG_IS_NULL;

 if((pll = pll->next) == NULL)
 {
  printf("%s\n", "no element in linklist.\n");
  return LINKLIST_IS_NULL;
 }

 while(pll)
 {
        if(pll->next == NULL)
        {
      printf("%2d*X^%1d ", pll->data.cst_term, pll->data.idx_term);
        }
        else
        {
      printf("%2d*X^%1d +", pll->data.cst_term, pll->data.idx_term);
        }
  pll = pll->next;
 }
 printf("\n");

 return SUCCESS;
}

/*
 *
 * 删除对应数据的节点
 *
 */
int locate_del_lnklst(linklist *pll, const data_t *data)
{
 linklist *prev = NULL;

 if(NULL == pll || data == NULL)
  return POINT_ARG_IS_NULL;

 prev = locate_lnklst(pll, data, NULL);
 if(NULL == prev)
  return NOT_FOUND;

 return del_head_lnklst(prev, NULL);
}

int add_linklist(linklist *a, linklist *b)
{
    linklist *tmp;
    if(NULL == a || NULL == b)
        return POINT_ARG_IS_NULL;

    if((b = b->next) == NULL)
    {
        return LINKLIST_IS_NULL;
    }

    while(b != NULL)
    {
        tmp = locate_lnklst(a, &b->data, NULL);
        if(NULL == tmp)
            ins_head_lnklst(a, &b->data);
        else
            tmp->next->data.cst_term += b->data.cst_term;
        b = b->next;
    }
    return 0;
}

/*
 *
 * A = 1 + 2*X + 3*X^2
 * B = 4 + 5*X + 6*X^2
 * R = A + B
 *   = 5 + 7*X + 9*X^2
 *
 */
int init_a_b(linklist *a, linklist *b)
{
    factor tmp;
    tmp.cst_term = 1;
    tmp.idx_term = 0;
    ins_head_lnklst(a, &tmp);
    tmp.cst_term = 2;
    tmp.idx_term = 1;
    ins_head_lnklst(a, &tmp);
    tmp.cst_term = 3;
    tmp.idx_term = 2;
    ins_head_lnklst(a, &tmp);

    tmp.cst_term = 4;
    tmp.idx_term = 0;
    ins_head_lnklst(b, &tmp);
    tmp.cst_term = 5;
    tmp.idx_term = 1;
    ins_head_lnklst(b, &tmp);
    tmp.cst_term = 6;
    tmp.idx_term = 2;
    ins_head_lnklst(b, &tmp);
    return 0;
}
int main(int argc, const char *argv[])
{
 linklist *fml_a = creat_lnklst();
 linklist *fml_b = creat_lnklst();
    init_a_b(fml_a, fml_b);

    printf("A =");
    print_lnklst(fml_a);

    printf("B =");
    print_lnklst(fml_b);

    add_linklist(fml_a, fml_b);
    printf("A + B =");
    print_lnklst(fml_a);
 return 0;
}

更多精彩内容其他人还在看

用标准c++实现string与各种类型之间的转换

这个类在头文件中定义, < sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本
收藏 0 赞 0 分享

C++如何通过ostringstream实现任意类型转string

再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上找了一下,发现有一个好方法
收藏 0 赞 0 分享

C/C++指针小结

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区
收藏 0 赞 0 分享

C++ 类的静态成员深入解析

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象
收藏 0 赞 0 分享

C++类的静态成员初始化详细讲解

通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化
收藏 0 赞 0 分享

C++类静态成员与类静态成员函数详解

静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值
收藏 0 赞 0 分享

C++中的friend友元函数详细解析

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样
收藏 0 赞 0 分享

static全局变量与普通的全局变量的区别详细解析

以下是对static全局变量与普通的全局变量的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
收藏 0 赞 0 分享

C++ explicit关键字的应用方法详细讲解

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?下面就让我们一起来看看这方面的知识吧
收藏 0 赞 0 分享

教你5分钟轻松搞定内存字节对齐

随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则
收藏 0 赞 0 分享
查看更多