数据结构主要分为线性结构和非线性结构
目录
dm_02_seqlist.cpp(实现每一个顺序表的基本操作)
关于void*和NULL
NULL #define NULL ((void *)0)
空指针有指向,但是它指向的地址是特殊的(0),在内存分配方面,较小的地址是不用来存放数据的,也不允许程序访问的,所以空指针不能操作该地址里的东西,我们就理解为“指针指向了空,无法操作了”。
void * 类型指针
这个类型指针指向了实实在在的存放数据的地址,但是该地址存放的数据的数据类型我们暂时不知道。所以先弄成void* 类型,后期一般要强制转换的(如指针++ -- 等操作,void*没有类型,步长不知道,必须强转,如(char*))。
顺序表
头文件(具体功能划分)
dm_02_seqlist.h
#pragma once
#include"iostream"
using namespace std;
typedef void Seqlist;
typedef void SeqlistNode;
Seqlist* SeqlistCreat(int capacity);//创建固定大小的线性表
void SeqlistDestory(Seqlist*list);//销毁线性表
void SeqlistClear(Seqlist*list);//清空
int SeqlistLength(Seqlist*list);//返回长度
int SeqlistCapacity(Seqlist*list);//返回容量
int SeqlistInsert(Seqlist*list, SeqlistNode*node,int pos);//指定位置插入节点
SeqlistNode* SeqlistGet(Seqlist*list, int pos);//获取指定位置节点
SeqlistNode*SeqlistDelete(Seqlist*list, int pos);//删除指定位置节点
dm_02_seqlist.cpp(实现每一个顺序表的基本操作)
#include"dm_02_seqlist.h"
struct TSeqlist
{
int len;//定义数组长度
int capacity;
unsigned int **node;//定义数组的首地址,二级指针 动态分配内存空间 或指针数组 每个元素均是一个指针 int *node[n];
//二级内存结构
};
//底层业务节点只是操作上层传入的指针,节点的内存由上层业务分配
//由于未知上层业务节点类型,故定义unsigneg int**指针类型,可以指向任何业务节点
Seqlist* SeqlistCreat(int capacity)
{
TSeqlist *tmp;
int ret = 0;
tmp = (TSeqlist*)malloc(sizeof(TSeqlist));//创建顺序表句柄
if (tmp == NULL)
{
ret = -1;
cout << "func SeqlistCreat malloc err" << ret << endl;
return NULL;
}
memset(tmp, 0, sizeof(TSeqlist));//初始化内存空间0
tmp->node = (unsigned int **)malloc(sizeof(unsigned int *)*capacity);
if (tmp->node == NULL)
{
ret = -2;
cout << "func SeqlistCreat malloc err" << ret << endl;
return NULL;
}
tmp->capacity = capacity;
tmp->len = 0;
return tmp;//Seqlist* 为void*型
}
//释放内存销毁链表
void SeqlistDestory(Seqlist*list)
{
TSeqlist*tlist = NULL;//自己知道数据类型
if (list == NULL)
{
cout << "传入为空指针" << endl;
return;
}
tlist = (TSeqlist*)list;
if (tlist->node != NULL)
{
free(tlist->node);
}
free(tlist);
}
//清空链表
void SeqlistClear(Seqlist*list)
{
TSeqlist*tlist = NULL;//自己知道数据类型
if (list == NULL)
{
cout << "传入为空指针" << endl;
return;
}
tlist->len = 0;//清空链表即回到初始化状态,len=0
}
//返回链表长度
int SeqlistLength(Seqlist*list)
{
if (list == NULL)
{
cout << "传入为空指针" << endl;
return -1;
}
TSeqlist*tlist = (TSeqlist*)list;
return tlist->len;
}
int SeqlistCapacity(Seqlist*list)
{
if (list == NULL)
{
cout << "传入为空指针" << endl;
return -1;
}
TSeqlist*tlist = (TSeqlist*)list;
return tlist->capacity;
}
//顺序表插入元素
int SeqlistInsert(Seqlist*list, SeqlistNode*node, int pos)
{
int ret = 0;
TSeqlist*tlist = (TSeqlist*)list;
//输入不合法
if (list == NULL || node == NULL || pos < 0)
{
ret = -1;
cout << "输入不合法 list == NULL || node == NULL || pos < 0 " << ret << endl;
return ret;
}
//顺序表已经满了
if (tlist->len == tlist->capacity)
{
ret = -2;
cout << "顺序表已经满了 tlist->len == tlist->capacity " << ret << endl;
return ret;
}
//顺序表没有满 插入位置大于len 即1到4 插到6、位置5空了
if (pos >= tlist->len)
{
pos = tlist->len;
}
//移动后面元素
for (int i = tlist->len; i > pos; i--)
{
tlist->node[i] = tlist->node[i-1];
}
//插入元素
tlist->node[pos] = (unsigned int*)node;//指针赋给指针
//若node为一级指针 则(unsigned int)将指针node转换为unsigned int型变量
tlist->len++;
return ret;
}
//读取节点
SeqlistNode* SeqlistGet(Seqlist*list, int pos)
{
SeqlistNode* ret = NULL;
TSeqlist*tlist = (TSeqlist*)list;
//输入不合法
if (list == NULL ||pos < 0 )
{
cout << "输入不合法 list == NULL || node == NULL || pos < 0" << ret << endl;
return ret;
}
ret = (SeqlistNode*)( tlist->node[pos]);
return ret;
}
//删除节点
SeqlistNode*SeqlistDelete(Seqlist*list, int pos)
{
SeqlistNode* ret = NULL;
TSeqlist*tlist = (TSeqlist*)list;
//输入不合法
if (list == NULL || pos < 0)
{
cout << "输入不合法 list == NULL || node == NULL || pos < 0 " << ret << endl;
return ret;
}
//移动后面元素
ret = (SeqlistNode*)(tlist->node[pos]);
for (int i = pos+1; i <tlist->len; i++)
{
tlist->node[i-1] = tlist->node[i];
}
tlist->len--;
return (SeqlistNode*)ret;
}
测试程序 main()
#include"dm_02_seqlist.h"
#include"iostream"
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
//SeqlistNode 为 void根本不不关心节点长啥样
//实际应用时(Teacher*) (SeqlistNode*)进行类型转换 顺序表和业务分离
struct Teacher {
int age;
char name[32];
};
void main02()
{
int size = 20;
int ret = 0;
Seqlist*list = NULL;
Teacher t1, t2, t3, t4;
strcpy(t1.name, "zhangsan22");
strcpy(t2.name, "lisi22");
strcpy(t3.name, "wangwu22");
strcpy(t4.name, "maliu22");
t1.age = 20;
t2.age = 22;
t3.age = 24;
t4.age = 26;
//建立链表
list = SeqlistCreat(10);
if (list == NULL)
{
ret = -1;
cout << "func SeqlistCreat err" << ret << endl;
return;//跳出main()函数
}
//头插
ret = SeqlistInsert(list,( SeqlistNode*)&t1, 0);//链表不关心具体的节点是啥(void),用到具体类型进行强制类型转换
ret = SeqlistInsert(list, (SeqlistNode*)&t2, 0);
ret = SeqlistInsert(list, (SeqlistNode*)&t3, 0);
ret = SeqlistInsert(list, (SeqlistNode*)&t4, 0);
if (list == NULL)
{
ret = -1;
cout << "func SeqlistInsert err" << ret << endl;
return;
}
//遍历
for (int i = 0; i < SeqlistLength(list); i++)
{
Teacher *tmp = (Teacher*)SeqlistGet(list, i);//上层应用知道自己传的是Teacher,别人不知道什么类型,
if (tmp == NULL)
{
ret = -2;
cout << "func SeqlistGet err" << ret << endl;
return;
}
cout<<tmp->name<< tmp->age << endl;
}
//删除
while (SeqlistLength(list)>0)
{
Teacher*tmp = NULL;
tmp = (Teacher*)SeqlistDelete(list, 0);//删0位置 即头
if (tmp == NULL)
{
ret = -3;
cout << "func SeqlistDelete err" << ret << endl;
return;
}
cout << tmp->name << '\t' << tmp->age << endl;
}
//检验是否删除完毕
for (int i = 0; i < SeqlistLength(list); i++)
{
Teacher *tmp = (Teacher*)SeqlistGet(list, i);//上层应用知道自己传的是Teacher,别人不知道什么类型,
if (tmp == NULL)
{
ret = -2;
cout << "func SeqlistGet err" << ret << endl;
return;
}
cout << tmp->name << tmp->age << endl;
}
}
测试结果:
基于顺序表的栈:
栈的头文件:
#pragma once
#ifndef __MY_SEQSTACK_H__
#define __MY_SEQSTACK_H__
typedef void SeqStack;
typedef void SeqNode;
SeqStack* SeqStack_Create(int capacity);
void SeqStack_Destroy(SeqStack * stack);
void SeqStack_Clear(SeqStack * stack);
void SeqStack_Push(SeqStack * stack, SeqNode*item);
SeqNode* SeqStack_Pop(SeqStack * stack);
SeqNode* SeqStack_Top(SeqStack * stack);
int SeqStack_Size(SeqStack * stack);
int SeqStack_Capacity(SeqStack * stack);
#endif //__MY_SEQLIST_H__
栈的实现文件:
#include"iostream"
#include"dm_06_seqStack.h"
using namespace std;
struct TseqStack {
int len;
int capacity;
unsigned int **node;
};
//栈是特殊的线性表 创建栈相当于创建线性表
SeqStack* SeqStack_Create(int capacity)
{
if (capacity <= 0)
{
cout << "SeqStack_Create err capacity <= 0 " << endl;
return NULL;
}
TseqStack *tseqStack = (TseqStack *)malloc(sizeof(TseqStack));
memset(tseqStack, 0, sizeof(tseqStack));
tseqStack->node = (unsigned int **)(malloc(sizeof(unsigned int *)*capacity));
tseqStack->capacity = capacity;
tseqStack->len = 0;
return tseqStack;
}
//销毁栈
void SeqStack_Destroy(SeqStack * stack)
{
if (stack == NULL)
{
cout << "SeqStack_Destroy err stack == NULL " << endl;
}
else
{
TseqStack *tseqStack = (TseqStack *)(stack);
tseqStack->capacity = 0;
tseqStack->len = 0;
if (tseqStack != NULL)
{
free(tseqStack);
}
}
}
//清空栈 等价于清空线性表
void SeqStack_Clear(SeqStack * stack)
{
if (stack == NULL)
{
cout << "SeqStack_Clear err stack == NULL " << endl;
}
else
{
TseqStack *tseqStack = (TseqStack *)(stack);
tseqStack->capacity = 0;
tseqStack->len = 0;
tseqStack = NULL;
}
}
//压栈 相当于线性表尾插法
void SeqStack_Push(SeqStack * stack, SeqNode*item)
{
if (stack == NULL|| item == NULL)
{
cout << "SeqStack_Push err stack == NULL|| item == NULL" << endl;
}
else
{
TseqStack *tseqStack = (TseqStack *)(stack);
if (tseqStack->len >= tseqStack->capacity)
{
cout << "SeqStack_Push err tseqStack->len >= tseqStack->capacity" << endl;
}
else
{
tseqStack->len++;//必须先加1 否则len为0则下一步无法读
tseqStack->node[tseqStack->len-1] = (unsigned int*)item;//下标从0开始,所以len-1
}
}
}
//弹栈 相当于从线性表尾部删除
SeqNode* SeqStack_Pop(SeqStack * stack)
{
TseqStack *tseqStack = (TseqStack *)(stack);
SeqNode* ret = NULL;
if (tseqStack == NULL)
{
cout << "SeqStack_Pop err stack == NULL" << endl;
return ret;
}
else
{
ret = (SeqNode*)tseqStack->node[tseqStack->len - 1];
tseqStack->len--;
return ret;
}
}
//获取站顶元素 相当于从线性表尾部读取
SeqNode* SeqStack_Top(SeqStack * stack)
{
TseqStack *tseqStack = (TseqStack *)(stack);
SeqNode* ret = NULL;
if (tseqStack == NULL)
{
cout << "SeqStack_Top err stack == NULL" << endl;
return ret;
}
else
{
ret = (SeqNode*)tseqStack->node[tseqStack->len - 1];
return ret;
}
}
int SeqStack_Size(SeqStack * stack)
{
int ret = 0;
TseqStack *tseqStack = (TseqStack *)(stack);
if (tseqStack == NULL)
{
cout << "SeqStack_Size err stack == NULL" << endl;
return ret;
}
else
{
ret = tseqStack->len;
return ret;
}
}
int SeqStack_Capacity(SeqStack * stack)
{
int ret = 0;
TseqStack *tseqStack = (TseqStack *)(stack);
if (tseqStack == NULL)
{
cout << "SeqStack_Size err stack == NULL" << endl;
return ret;
}
else
{
ret = tseqStack->capacity;
return ret;
}
}
栈的测试文件:
#include"dm_06_seqStack.h"
#include"iostream"
using namespace std;
struct Teacher_06 {
int age;
char name[32];
};
void main()
{
SeqStack*stack;
Teacher_06 t1, t2, t3, t4;
strcpy(t1.name, "zhangsan66");
strcpy(t2.name, "lisi66");
strcpy(t3.name, "wangwu66");
strcpy(t4.name, "maliu66");
t1.age = 20;
t2.age = 22;
t3.age = 24;
t4.age = 26;
stack = SeqStack_Create(10);
SeqStack_Push(stack, (SeqNode*)(&t1));
SeqStack_Push(stack, (SeqNode*)(&t2));
SeqStack_Push(stack, (SeqNode*)(&t3));
SeqStack_Push(stack, (SeqNode*)(&t4));
cout<<"stack_size"<<SeqStack_Size(stack)<<endl;
cout << "stack_capicity" << SeqStack_Capacity(stack) << endl;
Teacher_06 * tmp = (Teacher_06 *)SeqStack_Top(stack);
cout<<"stackTop"<< tmp->name<<" "<<tmp->age<<endl;
//弹栈 遍历
int len = SeqStack_Size(stack);
for (int i = 0; i<len ; i++)
{
tmp = (Teacher_06 *)SeqStack_Pop(stack);
cout << tmp->name << " " << tmp->age << endl;
}
system("pause");
}
栈的测试结果:
基于顺序表的队列:
队列的头文件:
#pragma once//包含一次 若被多个cpp文件包含则会导致在多个文件里重复编译出错
#include"iostream"
#include"dm_02_seqlist.h"
typedef void SeqQueue;
SeqQueue* SeqQueue_Create(int capacity);
void SeqQueue_Destroy(SeqQueue* queue);
void SeqQueue_Clear(SeqQueue* queue);
int SeqQueue_Append(SeqQueue* queue, void* item);
void* SeqQueue_Retrieve(SeqQueue* queue);
void* SeqQueue_Header(SeqQueue* queue);
int SeqQueue_Length(SeqQueue* queue);
int SeqQueue_Capacity(SeqQueue* queue);
队列的实现文件:
#include"iostream"
#include"dm_08_seqqueue.h"
Seqlist* SeqlistCreat(int capacity);
void SeqlistDestory(Seqlist*list);
void SeqlistClear(Seqlist*list);
int SeqlistLength(Seqlist*list);
int SeqlistCapacity(Seqlist*list);
int SeqlistInsert(Seqlist*list, SeqlistNode*node, int pos);
SeqlistNode* SeqlistGet(Seqlist*list, int pos);
SeqlistNode*SeqlistDelete(Seqlist*list, int pos);
SeqQueue* SeqQueue_Create(int capacity)
{
return SeqlistCreat( capacity);
}
void SeqQueue_Destroy(SeqQueue* queue)
{
SeqlistDestory((Seqlist*)(queue));
}
void SeqQueue_Clear(SeqQueue* queue)
{
SeqlistClear((Seqlist*)(queue));
}
int SeqQueue_Append(SeqQueue* queue, void* item)
{
int ret = -1;
ret = SeqlistInsert((Seqlist*)(queue), (SeqlistNode*)(item), SeqQueue_Length(queue));//len比下标大1 插入位置为尾部下标后的一个位置刚好是len
if (ret != 0)
{
cout << "SeqQueue_Append err ret" << ret << endl;
}
return ret;
}
//出队列相当于从线性表中删除0号位置元素
void* SeqQueue_Retrieve(SeqQueue* queue)
{
SeqlistNode*ret = SeqlistDelete((Seqlist*)(queue),0);
if (ret == NULL)
{
cout << "SeqQueue_Retrieve err" << endl;
}
return (void*)ret;
}
//获取队列头部 相当于从线性表中获取0号元素
void* SeqQueue_Header(SeqQueue* queue)
{
SeqlistNode*ret = SeqlistGet((Seqlist*)(queue), 0);
if (ret == NULL)
{
cout << "SeqQueue_Header err" << endl;
}
return (void*)ret;
}
//相当于获取线性表长度
int SeqQueue_Length(SeqQueue* queue)
{
return SeqlistLength((Seqlist*)(queue));
}
int SeqQueue_Capacity(SeqQueue* queue)
{
return SeqlistCapacity((Seqlist*)(queue));
}
队列的测试文件:
#include"iostream"
#include"dm_08_seqqueue.h"
using namespace std;
struct Teacher_08 {
int age;
char name[32];
};
void main()
{
SeqQueue*seqqueue;
Teacher_08 t1, t2, t3, t4;
strcpy(t1.name, "zhangsan66");
strcpy(t2.name, "lisi66");
strcpy(t3.name, "wangwu66");
strcpy(t4.name, "maliu66");
t1.age = 20;
t2.age = 22;
t3.age = 24;
t4.age = 26;
seqqueue = SeqQueue_Create(4);
SeqQueue_Append(seqqueue, (void*)(&t1));
SeqQueue_Append(seqqueue, (void*)(&t2));
SeqQueue_Append(seqqueue, (void*)(&t3));
SeqQueue_Append(seqqueue, (void*)(&t4));
//队列的属性
cout << "seqqueue_capacity" << SeqQueue_Capacity(seqqueue) << endl;
cout << "seqqueuesize" << SeqQueue_Length(seqqueue) << endl;
Teacher_08 * tmp = (Teacher_08 *)SeqQueue_Header(seqqueue);
cout << "seqqueue header" << tmp->name << " " << tmp->age << endl;
//出队遍历
int len = SeqQueue_Length(seqqueue);
for (int i = 0; i<len; i++)
{
tmp = (Teacher_08 *)SeqQueue_Retrieve(seqqueue);
cout << tmp->name << " " << tmp->age << endl;
}
system("pause");
}
队列的测试结果:
第一次写博客,Mark一下,督促记录自己学习吧。