數據結構主要分爲線性結構和非線性結構
目錄
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一下,督促記錄自己學習吧。