順序表和基於順序表的棧和隊列的實現(c思想實現)

數據結構主要分爲線性結構和非線性結構

 


目錄

關於void*和NULL

順序表

頭文件(具體功能劃分)

dm_02_seqlist.cpp(實現每一個順序表的基本操作)

測試程序 main()

測試結果:

基於順序表的棧:

棧的頭文件:

棧的實現文件:

棧的測試文件:

棧的測試結果:

基於順序表的隊列:

隊列的頭文件:

隊列的實現文件:

隊列的測試文件:

隊列的測試結果:


關於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一下,督促記錄自己學習吧。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章