精华内容
下载资源
问答
  • 随着项目的深入,你会发现如果对于数据结构没有一个准确的把握和理解,那么如同瞎子过河,全靠蒙。所以在这里我将自己的一些看法和认识用文字的方式记录下来,一方面给读者看,一方面让我发现自己的不足。   作为...

           随着项目的深入,你会发现如果对于数据结构没有一个准确的把握和理解,那么如同瞎子过河,全靠蒙。所以在这里我将自己的一些看法和认识用文字的方式记录下来,一方面给读者看,一方面让我发现自己的不足。

     

    作为一个传统的电商项目,最难的地方也就在于数据库中表的关联,以及多表之间的查询关联,缕清楚表与表之间的关系,才能进行随心所欲的CRUD。我的上一篇文章简单的分析了部分表,那么现在我把所有的表给分析出来。

     

    第一张:tb_brand    品牌表 

    id     :  品牌id(主键)

    name  :品牌名称

    image :品牌图片地址

    letter :品牌的首字母

     

     

    第二张:tb_categoory    商品类目表

    id: 商品类目id(主键)

    name :商品名称

    parent_id : 父目类id,顶级类目填0

    is_parent : 是否为父节点,0为否,1为是

    sort : 排序指数,越小越靠前

     

     

    第三张:tb_category_brand   : 商品分类和品牌的中间表

    category_id  :商品类目id

    brand_id  :品牌id

     

    第四张:tb_sku    :sku表            表示具体的商品实体,如黑色的 64g的iphone 8

    id:sku表的id(主键)

    spu_id :  spu的id

    title :商品的标题

    images: 商品的图片,多个图片以','分开

    price :销售价格

    indexes:特有规格属性在spu属性模板中的对应下标组合

    own_spec:sku的特有规格参数键值对,json格式,反序列化时请使用linkedHashMap,保证有序

    enable :是否有效,0无效,1有效

    create_time :添加时间

    last_update_ time:最后修改时间

    第五张:tb_spu  :表描述的是一个抽象性的商品表,比如 iphone8';

    id:spu 的id(主键)

    title : 标题

    sub _title : 子标题

    cid1:一级目录id

    cid2:二级目录id

    cid3:三级目录id

    brand_id : 商品所属品牌id

    saleable :是否上架,0下架,1上架',

    valid :是否有效,0已删除,1有效

    create_time :添加时间

    last_update_time  :最后修改时间

     

     

     

     

    表与表之间的联系:一个品牌下有多个商品(spu),一对多关系';

                                    类目和商品(spu)是一对多关系,类目与品牌是多对多关系';

     

    展开全文
  • 商品规格数据结构商品表结构分析:1. 商品规格数据结构1.1 规格属性内容1.2 横表与数表1.3 表结构1.3.1 SpecGroup规格组1.3.2 SpecParam规格参数1.4 从面向对象的角度分析2. 商品表结构分析2.1 SPU和SKU2.2 表结构...

    1. 商品规格数据结构

    商品中都有属性,不同商品,属性往往不同。

    1.1 规格属性内容

    在生活中,我们很容易发现,虽然商品不同,规格不同。但是统一分类的商品,比如都是手机,其规格是一致的,但是值不一样。也就是说,商品的规格参数应该是与分类绑定的。每一个分类都有统一的规格参数模板,但不同商品其参数值可能不同

    因此:

    • 规格参数的名称(key)与值(value)应该分开来保存;
    • 一个分类,对应一套规格参数模板,只有规格参数key,没有值;
    • 一个分类对应多个商品,每个商品的规格值不同,每个商品对应一套规格的值。

    1.2 横表与数表

    值我们暂且不管,新增商品时,再来填写规格参数值即可,我们先思考规格参数模板(key)该如何设计。
    先看下规格参数的结构:
    在这里插入图片描述

    • 规格数据首先要分组,组内再有不同的规格参数
    • 不同分类,其分组名称也不同
    • 不停分类,组内属性也不同
      这样就意味着:有多少分类,就有多少分组。
      如果按照传统设计,我们会以规格参数作为数据库字段名。如品牌、型号都是字段,那么表的字段就会无限多。这样的表称为横表。一条信息,描述所有数据。例如:
      在这里插入图片描述
      我们不这样做,我们一条信息,只描述一条规格属性,也就是把规格参数作为字段的值,而非字段本身。这样的设计称为竖表设计。例如:
      在这里插入图片描述
      不过,规格和规格组也要单独保存,都采用竖表设计。所以我们有两张表:
      在这里插入图片描述
      如图:
      在这里插入图片描述

    1.3 表结构

    1.3.1 SpecGroup规格组

    规格参数分组表:tb_spec_group

    CREATE TABLE `tb_spec_group` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
      `cid` bigint(20) NOT NULL COMMENT '商品分类id,一个分类下有多个规格组',
      `name` varchar(50) NOT NULL COMMENT '规格组的名称',
      PRIMARY KEY (`id`),
      KEY `key_category` (`cid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='规格参数的分组表,每个商品分类下有多个规格参数组';
    

    在这里插入图片描述

    1.3.2 SpecParam规格参数

    规格参数表:tb_spec_param

    CREATE TABLE `tb_spec_param` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
      `cid` bigint(20) NOT NULL COMMENT '商品分类id',
      `group_id` bigint(20) NOT NULL,
      `name` varchar(255) NOT NULL COMMENT '参数名',
      `numeric` tinyint(1) NOT NULL COMMENT '是否是数字类型参数,true或false',
      `unit` varchar(255) DEFAULT '' COMMENT '数字类型参数的单位,非数字类型可以为空',
      `generic` tinyint(1) NOT NULL COMMENT '是否是sku通用属性,true或false',
      `searching` tinyint(1) NOT NULL COMMENT '是否用于搜索过滤,true或false',
      `segments` varchar(1000) DEFAULT '' COMMENT '数值类型参数,如果需要搜索,则添加分段间隔值,如CPU频率间隔:0.5-1.0',
      PRIMARY KEY (`id`),
      KEY `key_group` (`group_id`),
      KEY `key_category` (`cid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COMMENT='规格参数组下的参数名';
    

    在这里插入图片描述

    通用属性

    用一个布尔类型字段来标记是否为通用:

    • generic来标记是否为通用属性:
      • true:代表通用属性
      • false:代表sku特有属性

    搜索过滤

    与搜索相关的有两个字段:

    • searching:标记是否用作过滤
      • true:用于过滤搜索
      • false:不用于过滤
    • segments:某些数值类型的参数,在搜索时需要按区间划分,这里提前确定好划分区间
      • 比如电池容量,0 ~ 2000mAh,2000mAh ~ 3000mAh,3000mAh ~ 4000mAh

    数值类型

    某些规格参数可能为数值类型,这样的数据才需要划分区间,我们有两个字段来描述:

    • numberic:是否为数值类型
      • true:数值类型
      • false:不是数值类型
    • unit:参数的单位

    1.4 从面向对象的角度分析

    我们现在要表示规格参数的key,不要值。
    如果用java对象表示:首先可以知道其可以分成 组 和 组内属性 两部分。 组 和 组内属性 分别是两类事物。
    对组进行描述:对组内的共同特征进行抽取,可以采用java中的 类(class Group) 进行描述。将主体、基本信息、操作系统等看成类中的name字段,将每一个分组下对应的多个参数(主体下的 型号、入网年份)看成类中的List params,同时,每个组也会有一个属于自己的id来标识自己。

    在这里插入图片描述
    对组内属性进行描述 :上述的List params 又是一个新的事物, 同样也可采用 类(class Param) 的概念进行描述。同样有name(参数名)、id字段,同时还要有一个groupId来说明这些参数属于哪个组分类下的,这样就做到了Group表和Param表相互关联。同时,Group表中也应添加categoryId来说明这些规格组是属于哪个商品分类下的。但是,再考虑,规格参数属性里应该也要加入是否为数值类型的字段;若是,那还会衍生出一个新的字段Unit;由于有一些规格参数的字段将来是要做搜索的,因此还应该有判断该参数是否为搜索字段;如果可以搜索,同时又是数值类型,那还会有一个segment字段(字符串类型)。到此为止,规格参数就描述清楚了。

    2. 商品表结构分析

    乐优商城是一个全品类的电商网站,因此商品的种类繁多,每一件商品,其属性又有差别。为了更准确描述商品及细分差别,抽象出两个概念:SPU和SKU。

    2.1 SPU和SKU

    • SPU:Standard Product Unit (标准产品单位) ,一组具有共同属性的商品集

    • SKU:Stock Keeping Unit(库存量单位),SPU商品集因具体特性不同而细分的每个商品

    以图为例:
    在这里插入图片描述

    • 本页的 华为Mate10 就是一个商品集(SPU)
    • 因为颜色、内存等不同,而细分出不同的Mate10,如亮黑色128G版。(SKU)

    可以看出:

    • SPU是一个抽象的商品集概念,为了方便后台的管理
    • SKU才是具体要销售的商品,每一个SKU的价格、库存可能会不一样,用户购买的是SKU而不是SPU
    • 同一个SPU下的SKU有共有属性,也有特有属性

    2.2 表结构

    2.2.1 表结构分析

    其实,SKU的特有属性是商品规格参数的一部分。规格参数我们已经提前设计好了,每一个分类都有自己的规格参数。因此我们在设计商品表的时候不要设计特有属性,这些特性设计到规格参数里了。因此规格参数表里的generic字段对 特有属性还是通用属性 进行了区分。
    在这里插入图片描述
    也就是说,我们没必要单独对SKU的特有属性进行设计,它可以看做是规格参数中的一部分。这样规格参数中的属性可以标记成两部分:

    • 所有sku共享的规格属性(称为通用属性),我们记录在spu表中
    • 每个sku不同的规格属性(称为特有属性),我们记录在sku表中
      在这里插入图片描述

    2.2.2 SPU表

    2.2.2.1 spu表结构

    CREATE TABLE `tb_spu` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'spu id',
      `title` varchar(255) NOT NULL DEFAULT '' COMMENT '标题(商品名称)',
      `sub_title` varchar(255) DEFAULT '' COMMENT '子标题',
      `cid1` bigint(20) NOT NULL COMMENT '1级类目id',
      `cid2` bigint(20) NOT NULL COMMENT '2级类目id',
      `cid3` bigint(20) NOT NULL COMMENT '3级类目id',
      `brand_id` bigint(20) NOT NULL COMMENT '商品所属品牌id',
      `saleable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否上架,0下架,1上架',
      `valid` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否有效,0已删除,1有效',
      `create_time` datetime DEFAULT NULL COMMENT '添加时间',
      `last_update_time` datetime DEFAULT NULL COMMENT '最后修改时间',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=208 DEFAULT CHARSET=utf8 COMMENT='spu表,该表描述的是一个抽象的商品,比如 iphone8';
    

    由于SPU表中某些字段的值非常大,比如商品描述。

    因此为了不影响spu表的性能及查询速度,我们对表做了垂直拆分,将SPU的详情放到了另一张表:tb_spu_detail

    在这里插入图片描述
    注:

    • 垂直拆分:表字段过多,实现数据的解耦
    • 水平拆分:表数据量多(一张表有1万条数据,水平拆分成两个表,每个表5千条数据)数据库查询时做排序较麻烦,不过现在有很多中间件帮我们实现分表 查询、排序等。用在 订单表中,订单数据量很大,一张表存不下,必然要做水平拆分。

    2.2.2.2 spu_detail 表结构

    CREATE TABLE `tb_spu_detail` (
      `spu_id` bigint(20) NOT NULL,
      `description` text COMMENT '商品描述信息',
      `generic_spec` varchar(3000) NOT NULL DEFAULT '' COMMENT '通用规格参数数据',
      `special_spec` varchar(1000) NOT NULL COMMENT '特有规格参数及可选值信息,json格式',
      `packing_list` varchar(1000) DEFAULT '' COMMENT '包装清单',
      `after_service` varchar(1000) DEFAULT '' COMMENT '售后服务',
      PRIMARY KEY (`spu_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    2.2.2.3 spu中的规格参数

    前面讲过规格参数与商品分类绑定,一个分类下的所有SPU具有类似的规格参数。SPU下的SKU可能会有不同的规格参数,因此:

    • SPU中保存通用的规格参数信息。
    • SKU中保存特有规格参数。
    2.2.2.3.1 generic_spec字段

    generic_spec:保存通用规格参数信息的值,这里为了方便查询,使用了json格式。
    在这里插入图片描述
    json结构,其中都是键值对:

    • key:对应的规格参数的spec_param的id
    • value:对应规格参数的值
    2.2.2.3.2 special_spec字段

    由于SPU下的每一个sku,其值也都不一样,所以值会有很多,形成数组。

    因此我们在SPU中,会把特有属性的所有值都记录下来,形成一个数组:
    在这里插入图片描述
    也是json结构:

    • key:规格参数id
    • value:spu属性的数组

    问题:特有规格参数应该在sku中记录才对,为什么在spu中也要记录一份(聚合sku集合)?

    • 因为我们有时候需要把所有规格参数都查询出来,而不是只查询1个sku的属性。比如,商品详情页展示可选的规格参数时:

    在这里插入图片描述
    刚好符号我们的结构,这样页面渲染就非常方便了。

    2.2.3 SKU表

    2.2.3.1 sku表结构

    CREATE TABLE `tb_sku` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'sku id',
      `spu_id` bigint(20) NOT NULL COMMENT 'spu id',
      `title` varchar(255) NOT NULL COMMENT 'sku特有标题',
      `images` varchar(1000) DEFAULT '' COMMENT '商品的图片,多个图片以‘,’分割',
      `price` bigint(15) NOT NULL DEFAULT '0' COMMENT '销售价格,单位为分',
      `indexes` varchar(100) COMMENT '特有规格属性在spu属性模板中的对应下标组合',
      `own_spec` varchar(1000) COMMENT 'sku的特有规格参数,json格式',
      `enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否有效,0无效,1有效',
      `create_time` datetime NOT NULL COMMENT '添加时间',
      `last_update_time` datetime NOT NULL COMMENT '最后修改时间',
      PRIMARY KEY (`id`),
      KEY `key_spu_id` (`spu_id`) USING BTREE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='sku表,该表表示具体的商品实体,如黑色的64GB的iphone 8';
    

    还有一张stock表,代表库存;

    因为库存字段写频率较高,而SKU的其它字段(颜色、价格)以读为主,因此我们将两张表分离,读写不会干扰(垂直拆分)。

    2.2.3.2 stock库存表

    CREATE TABLE `tb_stock` (
      `sku_id` bigint(20) NOT NULL COMMENT '库存对应的商品sku id',
      `seckill_stock` int(9) DEFAULT '0' COMMENT '可秒杀库存',
      `seckill_total` int(9) DEFAULT '0' COMMENT '秒杀总数量',
      `stock` int(9) NOT NULL COMMENT '库存数量',
      PRIMARY KEY (`sku_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='库存表,代表库存,秒杀库存等信息';
    

    2.2.3.3 sku中的规格参数

    2.2.3.3.1 indexes字段

    在SPU表中,已经对特有规格参数及可选项进行了保存,结构如下:

    {
        "4": [
            "香槟金",
            "樱花粉",
            "磨砂黑"
        ],
        "12": [
            "2GB",
            "3GB"
        ],
        "13": [
            "16GB",
            "32GB"
        ]
    }
    
    

    这些特有属性如果排列组合,会产生12个不同的SKU,而不同的SKU,其属性就是上面备选项中的一个。

    比如:

    • 红米4X,香槟金,2GB内存,16GB存储
    • 红米4X,磨砂黑,2GB内存,32GB存储

    你会发现,每一个属性值,对应于SPUoptions数组的一个选项,如果我们记录下角标,就是这样:

    • 红米4X,0,0,0
    • 红米4X,2,0,1

    既然如此,我们就可以将不同角标串联起来,作为SPU下不同SKU的标示。这就是我们的indexes字段。
    在这里插入图片描述
    这个设计在商品详情页(页面渲染)会特别有用:当用户点击选中一个特有属性,你就能根据 角标快速定位到sku。

    2.2.3.3.2 own_spec字段

    看结构:

    {
    	"4":"香槟金",
    	"12":"2GB",
    	"13":"16GB"
    }
    

    保存的是特有属性的键值对。

    SPU中保存的是可选项,但不确定具体的值,而SKU中的保存的就是具体的值。

    展开全文
  • 简易商品管理系统 数据结构课程设计数据结构课程设计数据结构课程设计数据结构课程设计
  • 商城-商品规格管理-商品规格数据结构1.商品规格数据结构1.1.SPU和SKU1.2.数据库设计分析1.2.1.思考并发现问题1.2.2.分析规格参数1.2.3.SKU的特有属性1.2.4.搜索属性1.3.规格参数表1.3.1.表结构1.3.2.json结构分析 1....

    1.商品规格数据结构

    乐优商城是一个全品类的电商网站,因此商品的种类繁多,每一件商品,其属性又有差别。为了更准确描述商品及细分差别,抽象出两个概念:SPU和SKU,了解一下:

    1.1.SPU和SKU

    SPU:Standard Product Unit (标准产品单位) ,一组具有共同属性的商品集

    SKU:Stock Keeping Unit(库存量单位),SPU商品集因具体特性不同而细分的每个商品

    以图为例来看:
    在这里插入图片描述

    • 本页的 华为Mate10 就是一个商品集(SPU)
    • 因为颜色、内存等不同,而细分出不同的Mate10,如亮黑色128G版。(SKU)

    可以看出:

    • SPU是一个抽象的商品集概念,为了方便后台的管理。
    • SKU才是具体要销售的商品,每一个SKU的价格、库存可能会不一样,用户购买的是SKU而不是SPU

    1.2.数据库设计分析

    1.2.1.思考并发现问题

    弄清楚了SPU和SKU的概念区分,接下来我们一起思考一下该如何设计数据库表。

    首先来看SPU,大家一起思考下SPU应该有哪些字段来描述?

    id:主键
    title:标题
    description:描述
    specification:规格
    packaging_list:包装
    after_service:售后服务
    comment:评价
    category_id:商品分类
    brand_id:品牌
    

    似乎并不复杂,但是大家仔细思考一下,商品的规格字段你如何填写?
    在这里插入图片描述

    不同商品的规格不一定相同,数据库中要如何保存?

    再看下SKU,大家觉得应该有什么字段?

    id:主键
    spu_id:关联的spu
    price:价格
    images:图片
    stock:库存
    颜色?
    内存?
    硬盘?
    

    碰到难题了,不同的商品分类,可能属性是不一样的,比如手机有内存,衣服有尺码,我们是全品类的电商网站,这些不同的商品的不同属性,如何设计到一张表中?

    1.2.2.分析规格参数

    仔细查看每一种商品的规格你会发现:

    虽然商品规格千变万化,但是同一类商品(如手机)的规格是统一的,有图为证:

    华为的规格:
    在这里插入图片描述

    三星的规格:
    在这里插入图片描述

    也就是说,商品的规格参数应该是与分类绑定的。每一个分类都有统一的规格参数模板,但不同商品其参数值可能不同

    如下图所示:
    在这里插入图片描述

    1.2.3.SKU的特有属性

    SPU中会有一些特殊属性,用来区分不同的SKU,我们称为SKU特有属性。如华为META10的颜色、内存属性。

    不同种类的商品,一个手机,一个衣服,其SKU属性不相同。

    同一种类的商品,比如都是衣服,SKU属性基本是一样的,都是颜色、尺码等。

    这样说起来,似乎SKU的特有属性也是与分类相关的?事实上,仔细观察你会发现,SKU的特有属性是商品规格参数的一部分
    在这里插入图片描述

    也就是说,我们没必要单独对SKU的特有属性进行设计,它可以看做是规格参数中的一部分。这样规格参数中的属性可以标记成两部分:

    • 所有sku共享的规格属性(称为全局属性)
    • 每个sku不同的规格属性(称为特有属性)
      在这里插入图片描述

    1.2.4.搜索属性

    打开一个搜索页,我们来看看过滤的条件:
    在这里插入图片描述

    你会发现,过滤条件中的屏幕尺寸、运行内存、网路、机身内存、电池容量、CPU核数等,在规格参数中都能找到:
    在这里插入图片描述

    也就是说,规格参数中的数据,将来会有一部分作为搜索条件来使用。我们可以在设计时,将这部分属性标记出来,将来做搜索的时候,作为过滤条件。要注意的是,无论是SPU的全局属性,还是SKU的特有属性,都有可能作为搜索过滤条件的,并不冲突,而是有一个交集:
    在这里插入图片描述

    1.3.规格参数表

    1.3.1.表结构

    先看下规格参数表:

    CREATE TABLE `tb_specification` (
      `category_id` bigint(20) NOT NULL COMMENT '规格模板所属商品分类id',
      `specifications` varchar(3000) NOT NULL DEFAULT '' COMMENT '规格参数模板,json格式',
      PRIMARY KEY (`category_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品规格参数模板,json格式。';
    

    很奇怪是吧,只有两个字段。特别需要注意的是第二个字段:

    • specificatons:规格参数模板,json格式

    为什么是一个json?我们看下规格参数的格式:
    在这里插入图片描述

    如果按照传统数据库设计,这里至少需要3张表:

    • group:代表组,与商品分类关联
    • param_key:属性名,与组关联,一对多
    • param_value:属性备选值,与属性名关联,一对多

    这样程序的复杂度大大增加,但是提高了数据的复用性。

    我们的解决方案是,采用json来保存整个规格参数模板,不需要额外的表,一个字符串就够了。

    1.3.2.json结构分析

    先整体看一下:
    在这里插入图片描述

    • 因为规格参数分为很多组,所以json最外层是一个数组。
    • 数组中是对象类型,每个对象代表一个组的数据,对象的属性包括:
      • group:组的名称
      • params:该组的所有属性

    接下来是params:
    在这里插入图片描述

    主芯片这一组为例:

    • group:注明,这里是主芯片

    • params:该组的所有规格属性,因为不止一个,所以是一个数组。这里包含四个规格属性:CPU品牌,CPU型号,CPU频率,CPU核数。每个规格属性都是一个对象,包含以下信息:

      • k:属性名称
      • searchable:是否作为搜索字段,将来在搜索页面使用,boolean类型
      • global:是否是SPU全局属性,boolean类型。true为全局属性,false为SKU的特有属性
      • options:属性值的可选项,数组结构。起约束作用,不允许填写可选项以外的值,比如CPU核数,有人添10000核岂不是很扯淡
      • numerical:是否为数值,boolean类型,true则为数值,false则不是。为空也代表非数值
      • unit:单位,如:克,毫米。如果是数值类型,那么就需要有单位,否则可以不填。

    上面的截图中所有属性都是全局属性,我们来看看内存,应该是特有属性:
    在这里插入图片描述

    总结下:

    • 规格参数分组,每组有多个参数
    • 参数的 k代表属性名称,没有值,具体的SPU才能确定值
    • 参数会有不同的属性:是否可搜索,是否是全局、是否是数值,这些都用boolean值进行标记:
      • SPU下的多个SKU共享的参数称为全局属性,用global标记
      • SPU下的多个SKU特有的参数称为特有属性
      • 如果参数是数值类型,用numerical标记,并且指定单位unit
      • 如果参数可搜索,用searchable标记
    展开全文
  • 数据结构课程设计-商品货架管理(C语言)

    千次阅读 多人点赞 2020-07-10 12:35:31
    数据结构课程设计——商品货架管理(C语言,顺序栈) 一、问题描述 商品货架可以看成一个栈,栈顶商品的生产日期最早,栈底商品的生产日期最近。上货时,需要进行倒货架,以保证生产日期较近的商品在较下的位置。 二...

    数据结构课程设计——商品货架管理(顺序栈)

    一、问题描述

    商品货架可以看成一个栈,栈顶商品的生产日期最早,栈底商品的生产日期最近。上货时,需要进行倒货架,以保证生产日期较近的商品在较下的位置。

    二、基本要求

    针对一种特定商品,实现上诉管理过程。

    三、实现提示

    用栈模拟货架和周转空间。

    四、源程序

    #include <stdio.h>
    #include <string.h>//字符串 
    #include<time.h>//时间 
    #include<stdlib.h>
    #include <conio.h>
    #include <windows.h>
    #define size 3	//货架最大容量
    //商品信息结构体
    struct Data{
        int year;	//年份
        int month;	//月份
        int day;	//日期
    	int num;	//数量 
    	int data;	//保质期 
    	int num_1; 	//货件编号
    };
    //定义顺序栈 
    typedef struct{
    	struct Data sp[size];//看成数组 
    	int top;//栈顶 
    }seqstack; 
    
    void InitStack(seqstack *S1);
    int StackEmpty(seqstack *S1);
    int StackFull(seqstack *S1);
    void push(seqstack *S1,seqstack *S2);
    void pop(seqstack *S1,seqstack *S2);
    void find(seqstack *S1);
    void Print(seqstack *S1);
    void output(seqstack *S1);
    void print1(seqstack *S1);
    void del(seqstack *S1);
    void save(seqstack *S1);
    void menu();
    
    void InitStack(seqstack *S1){	//栈初始化
    	S1->top=-1;
    }
    int StackEmpty(seqstack *S1){	//判断栈是否空
    	if(S1->top==-1) return 1;
    	else return 0;
    }
    int StackFull(seqstack *S1){	//判断栈是否满
    	if(S1->top==size-1)return 1;
    	else return 0;
    }
    
    void push(seqstack *S1,seqstack *S2){	//商品货件上架(录入商品货件信息)
    	int i,n,m,j=0;
    	time_t t;
       	struct tm * lt;
       	time (&t);//获取Unix时间戳。
       	lt = localtime (&t);//转为时间结构。
    	struct Data p;
    	m=(lt->tm_year+1900)*365+(lt->tm_mon)*30+lt->tm_mday;
    	printf("------------欢迎进入商品上货界面!------------\n\n\n");
    	if(StackFull(S1))printf("\t*货架已满,无法上货!");
    	else{
    	printf("该货架最大容量为%d!,货架已有%d件货物!\n\n",size,S1->top+1);
    	do{
    		fflush(stdin);
    		printf("\n请输入本次上货的件数:");	//超过货架最大容量,重新输入
    		scanf("%d",&n);
    		if(n+S1->top+1>size) printf("\n该货架最大容量为%d且货架已有%d件货物!请重新输入!\n\n",size,S1->top+1);
    	}while(n+S1->top+1>size);  
    	for(j=0;j<n;j++){
    		printf("\n请输入第%d件货物的信息:\n",j+1);
    		printf("\n\to货件编号:");
    		scanf("%d",&p.num_1); 
    	do{
    		fflush(stdin);  	
    		printf("\n\to生产日期:");	//生产日期小于今天且规范,货件为近十年的货件
    		scanf("%d/%d/%d",&p.year,&p.month,&p.day);
    		if((p.year*365+(p.month-1)*30+p.day)>m||p.year<=0||p.year<(lt->tm_year+1890)||p.month<=0||p.month>12||p.day<=0||p.day>30)
    		printf("\n输入的生产日期不对!请重新输入!\n");
    		}while((p.year*365+(p.month-1)*30+p.day)>m||p.year<=0||p.year<(lt->tm_year+1890)||p.month<=0||p.month>12||p.day<=0||p.day>30);
    	do{
    		fflush(stdin);
    		printf("\n\to商品数量:");
    		scanf("%d",&p.num);
    		if(p.num<=0) printf("\n输入的数量不对!请重新输入!\n");
    	}while(p.num<=0);  
    		printf("\n\to保质期(天):");
    		scanf("%d",&p.data);
    		i=1;
    	while(S1->top!=-1&&((p.year*365+(p.month-1)*30+p.day)-(S1->sp[S1->top].year*365+(S1->sp[S1->top].month-1)*30+S1->sp[S1->top].day))>0){		//倒货
    		S2->top++;
    		S2->sp[S2->top]=S1->sp[S1->top];
    		S1->top--;				
    	}
    	S1->top++;
    	S1->sp[S1->top]=p;
    	for(;S2->top>-1;S2->top--){
    		S1->top++;
    		S1->sp[S1->top]=S2->sp[S2->top];
    		} 
    	}
    	if(i==1) printf("\n商品上架成功"); 
     }printf("\n\n\n返回上一层,");
     system("pause");
    system("cls");
    }
    
    void find(seqstack *S1){	//查询界面
    	int n,j;
    	printf("----------欢迎进入商品查询界面!----------\n\n");
    	if(StackEmpty(S1)) printf("\n\t*货架为空,无法查询,请先添加货物!\n"); 	//货架空
    	else{
    	do{
    		printf("\n【按 生产日期 查询输入1】\t【按 数量 查询输入2】\t【退出查询界面输入0】"); 
    		printf("\n\n\n请选择您的选项:");
    		scanf("%d",&n);	
    		switch(n){ 
    			case 1: 
    				{		//按生产日期查询
    				int month,year,day;
      				int i=0; 
    				printf("\n请输入要查询的日期:");
    				scanf("%d/%d/%d",&year,&month,&day); 
    				for(j=S1->top;j>=0;j--){
    				if(S1->sp[j].year==year&&S1->sp[j].month==month&&S1->sp[j].day==day){
    				if(i==0) printf("\n%d年%d月%d日生产的旺仔牛奶如下:\n\n",year,month,day); 	//存在该货件
    				if(i==0) printf("\t货件编号\t生产日期\t保质期(天)\t商品数量\n\n");
    				printf("\t%d",S1->sp[j].num_1); 
    				printf("\t\t%d/%d/%d",S1->sp[j].year,S1->sp[j].month,S1->sp[j].day);
    				printf("\t%d",S1->sp[j].data);
    				printf("\t\t%d",S1->sp[j].num);
    				printf("\n\n");
    				i=1;
    				}
    			}
    				if(i==0) printf("\n\n\t无%d/%d/%d生产的旺仔牛奶!\n",year,month,day);		//无该货件
    				printf("\n\n----------------------------------------\n\n"); 
    				break;
    				}
    			case 2:
    				{int num;		//按数量查询
    				int i=0;
    				printf("\n请输入要查询的数量:");
    				scanf("%d",&num); 
    				for(j=S1->top;j>=0;j--){
    				if(S1->sp[j].num<=num){
    				if(i==0) printf("\n货架上%d件以下的旺仔牛奶如下:\n\n",num);  
    				if(i==0) printf("\t货件编号\t生产日期\t保质期(天)\t商品数量\n\n");		//存在该数量以下的货件
    				printf("\t%d",S1->sp[j].num_1); 
    				printf("\t\t%d/%d/%d",S1->sp[j].year,S1->sp[j].month,S1->sp[j].day);
    				printf("\t%d",S1->sp[j].data);
    				printf("\t\t%d",S1->sp[j].num);
    				printf("\n\n");
    				i=1;
    				}
    			}
    				if(i==0) printf("\n\n\t无%d件以下的旺仔牛奶!\n",num); 		//无此类货件
    				printf("\n----------------------------------------\n\n"); 
    				break;
    			}
    		}
    		}while(n!=0);
    	}printf("\n\n返回上一层,"); 
    	system("pause");
    	system("cls");		
    }
    
    void Print(seqstack *S1){		//货架的货件信息
    	int j;
    	printf("----------欢迎进入货架清单界面!----------\n\n\n");
    	if(StackEmpty(S1)) printf("\t*货架为空,请先添加货物!\n"); 	//货架空
    	else{
    		print1(S1);
    	}
    	printf("\n\n返回上一层,");
    	system("pause");
    	system("cls"); 
    }
    
    void print1(seqstack *S1){
    	int j;
    	printf("货架清单如下:\n\n");
    	printf("\t货件编号\t生产日期\t保质期(天)\t商品数量\n\n");
    	for(j=S1->top;j>=0;j--){
    		printf("\t%d",S1->sp[j].num_1); 
    		printf("\t\t%d/%d/%d",S1->sp[j].year,S1->sp[j].month,S1->sp[j].day);
    		printf("\t%d",S1->sp[j].data);
    		printf("\t\t%d",S1->sp[j].num);
    		printf("\n\n");
    		}
    } 
    
    void pop(seqstack *S1){		//货件出架
    	int j,num_1,num;
    	printf("------------欢迎进入商品出货界面!------------\n\n\n");
    	if(StackEmpty(S1)) printf("\t*货架为空,请先添加货物!\n");	///货架空
    	else{
    		print1(S1);
    		printf("请输入您要出货货件的编号:");
    		scanf("%d",&num_1);
    		for(j=S1->top;j>=0;j--){
    		if(S1->sp[j].num_1==num_1){
    		do{
    			fflush(stdin);		//输入的出货件数需小于该货件原本有的货件数量
    			printf("\n请输入该货件出货数量:");
    			scanf("%d",&num);
    			if(num>S1->sp[j].num)
    			printf("该货件无%d件商品,请重新输入!\n"); 
    			}while(num>S1->sp[j].num);
    		S1->sp[j].num-=num;
    		printf("\n\t出货成功!");
    		if(S1->sp[j].num<20) printf("该货件商品小于20件!\n");	//出货后数量小于20会提示上货
    		break;
    			}
    	}
    	}printf("\n\n返回上一层,"); 
    	system("pause");
    	system("cls");
    } 
    
    void del(seqstack *S1,seqstack *S2){	//删除货件
    	char name[20];
    	int num_1,T,j;
    	struct Data p1;
    	printf("------------欢迎进入商品删除界面!------------\n\n\n");
    	if(StackEmpty(S1)) printf("\t*货架为空,请先添加货物!\n");	//货架空
    	else{
    	print1(S1);
    	printf("请输入您要删除货件的编号:");
    	scanf("%d",&num_1); 
    	for(j=S1->top;j>=0;j--){
    		if(S1->sp[j].num_1==num_1){
    			while(S1->top>j){
    				S2->top++;
    				S2->sp[S2->top]=S1->sp[S1->top];
    				S1->top--;
    			}
    			p1=S1->sp[S1->top];
    			S1->top--;
    			for(;S2->top>-1;S2->top--){
    				S1->top++;
    				S1->sp[S1->top]=S2->sp[S2->top];
    			}
    			printf("\n\n\t该货件删除成功!\n");
    			break;}
    		}
    		}
    	printf("\n\n返回上一层,");
    	system("pause");
    	system("cls"); 
    }
    
    void outdata(seqstack *S1){		//打印过期货件
    	int m,i=0,j;
    	time_t t;
       	struct tm * lt;
       	time (&t);//获取Unix时间戳。
       	lt = localtime (&t);//转为时间结构。
        m=(lt->tm_year+1900)*365+(lt->tm_mon)*30+lt->tm_mday;	//当前系统时间
        if(StackEmpty(S1)) printf("\t*货架为空,请先添加货物!\n");	//货架空
        else{
    	for(j=S1->top;j>=0;j--){
    	if((S1->sp[j].year*365+(S1->sp[j].month-1)*30+S1->sp[j].day+S1->sp[j].data)<m){
    	if(i==0) printf("已过期的旺仔牛奶如下(今日日期为:%d/%d/%d):\n\n",lt->tm_year+1900,lt->tm_mon+1,lt->tm_mday);
    	if(i==0) printf("\t货件编号\t生产日期\t保质期(天)\t商品数量\n\n");
    	printf("\t%d",S1->sp[j].num_1); 
    	printf("\t\t%d/%d/%d",S1->sp[j].year,S1->sp[j].month,S1->sp[j].day);
    	printf("\t%d",S1->sp[j].data);
    	printf("\t\t%d",S1->sp[j].num);
    	printf("\n\n");
    	i=1;
    		}
    	}
    	if(i==0) printf("\n\t货架无过期的旺仔牛奶!\n"); }
    	printf("\n\n返回上一层,");
    	system("pause");
    	system("cls");
    } 
    
    void save(seqstack *S1){	//保存货件信息
    	int i,j;
    	FILE *fp; 
    	if(StackEmpty(S1)) printf("\t*货架为空,请先添加货物!\n");   //货架空
    	else{
    	fp=fopen("goods.txt","w");
    	if(!fp){
    		printf("文件不存在\n");
    		return;
    	}
    	//将商品信息写入文件
        fprintf(fp,"===========================商品信息一览表===========================\n");
        fprintf(fp,"\n");
       	fprintf(fp,"货件编号\t\t生产日期\t\t保质期(天)\t\t商品数量\n\n");
       	for(j=S1->top;j>=0;j--){
    		fprintf(fp,"%d",S1->sp[j].num_1); 
    		fprintf(fp,"\t\t%d/%d/%d",S1->sp[j].year,S1->sp[j].month,S1->sp[j].day);
    		fprintf(fp,"\t\t%d",S1->sp[j].data);
    		fprintf(fp,"\t\t%d",S1->sp[j].num);
    		fprintf(fp,"\n\n");
    		}
        fclose(fp); 	 //把缓冲区内最后剩余的数据输出到内核缓冲区,并释放文件指针
        printf("数据已成功导入文件goods.txt!\n"); 
    	printf("\n                              √保存成功!");
    	}
       	printf("\n\n返回上一层,");
    	system("pause");
    	system("cls");
    } 
    void menu(){
    	printf("\n\n\n");
    	printf("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳ “旺仔牛奶 ”货架 ┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");
    	printf("\n\n");
    	system("color DF"); 
    	printf("\t\t\t ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┃       请选择您要操作的项目      ┃\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┃            1 上货               ┃\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┃            2 出货               ┃\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┃            3 查询               ┃\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┃            4 过期货件           ┃\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┃            5 货架清单           ┃\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┃            6 删除货件           ┃\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┃            7 保存操作           ┃\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┃            0 退出系统           ┃\n");
        printf("\t\t\t ┃                                 ┃\n");
        printf("\t\t\t ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");
    
    }
    int main(){
    	seqstack A,B;
    	InitStack(&A);
    	InitStack(&B);
    //值等于栈顶 
    	int i;
    	do{
    		menu();
    		printf("\n\n");
    		printf("  *请输入您的选择(0 - 6):");
    		scanf("%d",&i);
    		printf("\n\n");
    		switch(i){
    			case 1:push(&A,&B);
    				   	break;  //创建top 
    			case 2:pop(&A);
    					break;
    			case 3:find(&A);
    					break;	
    			case 4:outdata(&A);
    					break;
    			case 5:Print(&A);
    					break;
    			case 6:del(&A,&B);
    					break;
    			case 7:save(&A);
    					break; 
    			case 0:printf("正在退出该系统,欢迎下次使用!\n\n");
    					for(int i=0;i<30;i++){
    						Sleep(150);
    						printf("<<"); 
    					}
    					system("cls");
    					break; 
    			default:
    				printf("请输入正确的选项!\n\n");
    					system("pause");
    					system("cls");;
    					break; 
    		}
    	}while(i!=0);
    	return 0;
    }
    

    五、各功能介绍

    1.上货
    (1)先判断栈是否满
    (2)满,提示货架已满,无法上货,否则,输入需要上货的件数,添加货件的信息,即完成上货

    2.出货
    (1)先判断货件是否空
    (2)空,提醒上货,否则,根据货架清单输入出货货件的编号和数量,完成出货

    3.查询
    (1)先判断栈是否空
    (2)空,提醒上货,否则,根据菜单输入相依编号(1.按生产日期,2.数量,0.退出查询),然后根据需入的编号找相应货件,存在,输出该货件信息,否则,打印“无此商品”

    4.打印过期货件
    (1)先判断栈是否空
    (2)空,提醒上货,否则,看货架是否存在过期货件,输出相应的结果

    5.删除货件
    (1)先判断栈是否空
    (2)空,提醒上货,否则,根据货架信息输入删除货件的编号,删除该货件

    6.打印货架清单
    (1)先判断栈是否空
    (2)空,提醒上货,否则,打印出货架的全部货件信息

    7.保存操作
    (1)先判断货架是否空
    (2)空,提醒上货,否则,保存

    六、程序运行截图

    1.菜单界面
    在这里插入图片描述
    2.录入货件信息
    在这里插入图片描述
    浏览当前输入的货件信息
    在这里插入图片描述
    3.货件出货

    货架为空
    在这里插入图片描述
    出货
    在这里插入图片描述
    出货后货架信息
    在这里插入图片描述
    3.查询货件

    货架为空
    在这里插入图片描述
    按生产日期查询
    在这里插入图片描述
    按数量查询
    在这里插入图片描述

    4.打印过期货件

    货架为空
    在这里插入图片描述
    存在过期货件
    在这里插入图片描述
    无过期货件
    在这里插入图片描述
    5.打印货架清单

    货架为空
    在这里插入图片描述
    货架清单
    在这里插入图片描述
    6.删除货件

    货架为空
    在这里插入图片描述
    删除后的货件
    在这里插入图片描述
    删除后货架清单
    在这里插入图片描述
    7.保存操作

    货架为空
    在这里插入图片描述
    保存成功
    在这里插入图片描述
    在这里插入图片描述
    8.退出系统
    在这里插入图片描述

    展开全文
  • 1.商品规格数据结构 1.1.SPU和SKU 1.2.数据库设计分析 1.2.1.思考并发现问题 1.2.2.分析规格参数 1.2.3.SKU的特有属性 1.3.规格参数表 1.3.1.表结构 1.3.2.json结构分析 2.商品规格参数管理 2.1.页面实现 ...
  • 这是一个数据结构课程设计题商品管理系统,用C语言写的,该商品管理系统包含商品录入功能,商品增加功能,商品删除功能,商品更新功能,商品查询功能,商品保存到文件功能和从文件中导入商品信息功能。里面还有商品...
  • 商品货架可以看成一个栈,栈顶商品的生产日期最早,栈底商品的生产日期最近。 上货时,需要倒货架,以保证生产日期较近的商品在较下的位置。
  • 数据结构——商品货架管理(C++实现) 源代码

    千次阅读 多人点赞 2018-10-29 19:56:58
    *尚品货架可以看成一个栈,栈顶商品的生产日期最早,栈底商品的生产日期最近。 *上货时,需要倒货架,以保证生产日期较新的商品在较靠里的位置   针对一种特定商品,实现上述管理过程 测试数据:由学生自己确定一...
  • 电商网站采用在商品模块,常采用spu+sku的数据结构算法,这种算法可以将商品的属性和商品的基本信息分离,分开维护,这样我们就可以在不同的类目下自定义商品信息和分类的属性信息,我们的业务系统就可以存储不同...
  • 刚做完的数据结构课程设计 用双链表实现;MFC做的;
  • 深刻的体会到了,MongoDB可以不设计集合的结构和数据类型即可使用,但不代表它不需要数据结构设计。一个好的系统运作,肯定需要对MongoDB的数据结构进行合理的设计才能高效运行。当然,我也不建议在业务初期就进行...
  • 商城-商品规格管理-SPU和SKU数据结构

    千次阅读 2019-06-14 23:58:25
    商城-商品规格管理-SPU和SKU数据结构3.SPU和SKU数据结构3.1.SPU表3.1.1.表结构3.1.2.spu中的规格参数3.1.2.1.specifications字段3.1.2.2.spec_template字段3.2.SKU表3.2.1.表结构3.2.2.sku中的特有规格参数3.2.2.1....
  • 最终一致性 数据结构与算法 冒泡排序 选择排序 快速排序 递归 二分查找 一致性Hash算法 概述 一致性Hash算法原理 Java面试总结汇总,整理了包括Java基础知识,集合容器,并发编程,JVM,常用开源框架Spring,...
  • 学习数据数据结构的意义

    千次阅读 2018-12-31 14:09:05
    什么是数据结构,为什么要学习数据结构数据结构是否是一门纯数学课程?它在专业课程体系中起什么样的作用?我们要怎么才能学好数据结构?… 相信同学们在刚开始《数据结构》这门课的学习时,心里有着类似前面几个...
  • 从淘宝数据结构来看电子商务中商品属性设计http://www.cnblogs.com/mmmjiang13/archive/2011/04/21/1983079.html淘宝商品数据库设计:http://www.cnblogs.com/mmmjiang13/archive/2010/11/04/1868609.html
  • 电商网站采用在商品模块,常采用spu+sku的数据结构算法,这种算法可以将商品的属性和商品的基本信息分离,分开维护,这样我们就可以在不同的类目下自定义商品信息和分类的属性信息,我们的业务系统就可以存储不同...
  • Java生鲜电商平台-商品的spu和sku数据结构设计与架构 1. 先说明几个概念. 电商网站采用在商品模块,常采用spu+sku的数据结构算法,这种算法可以将商品的属性和商品的基本信息分离,分开维护,这样我们就可以在...
  • 数据结构课程设计 - 超市商品管理系统

    千次阅读 多人点赞 2017-12-21 09:05:23
    一.源程序代码  1. 头文件 goods.h #ifndef GOODS_H_INCLUDED #define GOODS_H_INCLUDED #include #include #include #include #include #define MAXSIZE 100 ...typedef struct //数据域定义为一个
  • json数据结构

    千次阅读 2019-04-18 20:32:14
    一、使用中,json有以下三种结构: 对象:{“name”:“Michael”,“age”:24} 数组:比如:[{“name”:“Michael”,“age”:24},{“name”:“Tom”,“age”:25}] 值:{“name”:“Michael”, “birthday”:{“month...
  • 数据结构作用

    千次阅读 2008-05-04 15:12:00
    数据结构是对在计算机内存中(有时在磁盘中)的数据的安排。数据结构包括数组、链表、栈、二又树、哈希表等等。算法对这些结构中的数据进行各种处理,例如,想找一条特殊的数据项或对数据进行排序 掌握这些知识以后...
  • python数据结构

    千次阅读 2007-04-03 12:53:00
    数据结构是一种结构,它们用以把一些数据存储在一起。在python中有三种内建的数据结构:列表(list)、元组(tuple)、字典(dictionary)。1、列表列表由一对方括号括起来,其中的项目之间以逗号分隔。你可以在列表中增加...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 134,343
精华内容 53,737
关键字:

商品数据结构

数据结构 订阅