梯次表简介
顺序表就是为数组的形式来存储和治本事务节点。具体的数据结构如下图:
鉴于达到图能够,seqlist结构体就是现实的顺序表数据结构,length变量表示存储的业务节点的个数,capacity变量表示pnode指向的堆区空间容量。该堆区是一个指针数组,每一个数组元素存储一个工作节点的地点,来针对各个业务节点,因此,管理之指针数组的凡一个二级指针pnode;
头文件说明
//seqlist.h
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
typedef void SeqList;
typedef void SeqListNode;
typedef struct tag_SeqList{
int length;
int capacity;
unsigned int **pnode;
}TSeqList;
//创建并且返回一个空的线性表
SeqList *SeqList_Create(int capacity);
//销毁一个线性表
void SeqList_Destroy(SeqList* plist);
//将一个线性表list中的所有元素清空,线性表回到创建时的状态
void SeqList_Clear(SeqList* plist);
//返回一个线性表list中的所有元素个数
int SeqList_Length(SeqList* plist);
//向一个线性表list的pos位置处插入新元素node节点
int SeqList_Insert(SeqList* plist, SeqListNode* pnode, int pos);
//获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* plist, int pos);
//删除一个线性表list的pos位的node节点元素,返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* plist, int pos);
//遍历顺序表
#define SeqList_Traverse(plist,node_type,number) \
({ \
int i;\
for(i=0; i < plist->length; i++) { \
printf("number: %d\n",((typeof(node_type)*)(plist->pnode[i]))->number);\
} })
#endif //seqlist.h
seqlist.h头文件是指向顺序表数据结构和效力接口的空洞。在就中间,主要注意一下几碰:
- SeqList和SeqListNode的数据类型:
是以void数据类型的包。原因之一是增长代码的可读性,其二,将void封装,是为配合更多种类型的事体节点。 - 为宏函数形式遍历顺序表:先是,我想说名的少数凡,遍历的功效实在以咱们规划数据结构的操作函数时是未曾必要设计之。我们统筹之是对准工作节点的田间管理,是“增删改查”,“查”本就足以收获想使的政工节点,但当我设计是,我们经常会涉嫌遍历的意义,可于自身设计时发现,数组指针中数组元素指向的事情节点的数据类型不确定,所以无法用printf函数直接打印想要之节点数据。想尝尝的解决这个题材,于是我才设计了这宏函数。不用定义的函数的艺术去实现遍历功能,是坐无法在展示参中直接拿走工作节点的数据类型,只能通过大的样式取得工作节点的数据类型。测试代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct a{
char ch;
int num;
}A;
int main ()
{
A a;
void *ptype = NULL;
ptype = (void *)&a;
printf("%lu\n",sizeof(typeof(ptype)));
return 0;
}
运行的结果是:4,而不是8。得到的凡ptype指针的数据类型,而无是struct
a这种多少列。如果我们所以定义函数的法而休是概念宏函数之道去贯彻遍历时,那么,我们吸收工作节点的形参只能是“void
*”类型,但我们鞭长莫及在函数内部用typeof关键子获取到形参指向的数码的数据类型,而宏函数能好。
成效函数实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "seqlist.h"
//创建并且返回一个空的线性表
SeqList *SeqList_Create(int capacity)
{
TSeqList *plist = NULL;
plist = (TSeqList*)malloc(sizeof(TSeqList));
memset(plist, 0, sizeof(TSeqList));
if(NULL == plist)
{
perror("SeqList_Create TSeqList");
return NULL;
}
plist->pnode = (unsigned int**)malloc(sizeof(unsigned int)*capacity);
memset(plist->pnode, 0, sizeof(unsigned int)*capacity);
if(NULL == plist->pnode)
{
perror("SeqList_Create pnode");
return NULL;
}
//plist->length = 0;
plist->capacity = capacity;
return plist;
}
//销毁一个线性表
void SeqList_Destroy(SeqList* plist)
{
TSeqList *ptlist = (TSeqList*)plist;
if(NULL == ptlist)
{
printf("SeqList is empty(SeqList_Destroy)!\n ");
return ;
}
if(ptlist->pnode != NULL)
{
free(ptlist->pnode);
}
free(plist);
return ;
}
//将一个线性表list中的所有元素清空,线性表回到创建时的状态
void SeqList_Clear(SeqList* plist)
{
TSeqList *ptlist = (TSeqList*)plist;
if(NULL == ptlist)
{
printf("SeqList is empty(SeqList_Clear)!\n ");
return ;
}
ptlist->length = 0;
return ;
}
//返回一个线性表list中的所有元素个数
int SeqList_Length(SeqList* plist)
{
TSeqList *ptlist = (TSeqList*)plist;
if(NULL == ptlist)
{
printf("SeqList is empty(SeqList_Length)!\n ");
return -1;
}
return ptlist->length;
}
//向一个线性表list的pos位置处插入新元素node节点
int SeqList_Insert(SeqList* plist, SeqListNode* pnode, int pos)
{
TSeqList *ptlist = (TSeqList*)plist;
if(NULL == ptlist || NULL == pnode )
{
printf("SeqList is empty(SeqList_Insert)!\n ");
return -1;
}
if( pos<-1 || pos >= ptlist->capacity )
{
printf("pos is unvalid(SeqList_Insert)!\n");
return -2;
}
int i;
for(i=ptlist->length; i>pos; i--)
ptlist->pnode[i] = ptlist->pnode[i-1];
ptlist->pnode[pos] = (unsigned int*)pnode;
ptlist->length ++;
return 0;
}
//获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* plist, int pos)
{
TSeqList *ptlist = (TSeqList*)plist;
if(NULL == ptlist)
{
printf("SeqList is empty(SeqList_Get)!\n ");
return NULL;
}
if( pos<-1 || pos > ptlist->capacity )
{
printf("pos is unvalid(SeqList_Insert)!\n");
return NULL;
}
return ptlist->pnode[pos];
}
//删除一个线性表list的pos位的node节点元素,返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* plist, int pos)
{
TSeqList *ptlist = (TSeqList*)plist;
if(NULL == ptlist)
{
printf("SeqList is empty!(SeqList_Delete)\n ");
return NULL;
}
if( pos<-1 || pos > ptlist->capacity )
{
printf("pos is unvalid!(SeqList_Delete)\n");
return NULL;
}
SeqListNode *pnode = NULL;
pnode = (SeqListNode*)ptlist->pnode[pos];
int i;
for(i=pos; i < ptlist->length; i++)
ptlist->pnode[i] = ptlist->pnode[i+1];
ptlist->length --;
return pnode;
}
成效测试代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "seqlist.h"
typedef struct student{
char name[20];
int age;
}student;
int main(int argc, char *argv[])
{
student stu1,stu2,stu3,stu4,stu5;
stu1.age = 20;
stu2.age = 21;
stu3.age = 22;
stu4.age = 23;
stu5.age = 24;
TSeqList *pslist = (TSeqList*)SeqList_Create(5);
SeqList_Insert(pslist, (SeqListNode*)&stu1, 0);
SeqList_Insert(pslist, (SeqListNode*)&stu2, 1);
SeqList_Insert(pslist, (SeqListNode*)&stu3, 2);
SeqList_Insert(pslist, (SeqListNode*)&stu4, 3);
SeqList_Insert(pslist, (SeqListNode*)&stu5, 4);
printf("length: %d\n",SeqList_Length(pslist));
SeqList_Traverse(pslist,student,age);
SeqList_Delete(pslist,2);
printf("length: %d\n",SeqList_Length(pslist));
int i;
student *ptmp = NULL;
for(i=0; i < SeqList_Length(pslist); i++)
{
ptmp = SeqList_Get(pslist,i);
printf("age: %d\n",ptmp->age);
}
SeqList_Clear(pslist);
SeqList_Destroy(pslist);
return 0;
}
总结
学数据结构我们设开的不只是学习数据结构的算法实现,更要紧之凡能够写起同种植有普适性的家伙,站于一个复强的设计策略的角度去设计代码,这点对学数据结构来说很重点,没有及时点召开支撑,学到的数据结构就独自是一个空壳子,无法活的使。