1. 程式人生 > 其它 >03-資料結構(C語言版)

03-資料結構(C語言版)

Day01

筆記

1	資料結構基本理論
	1.1	演算法五個特性:
		1.1.1	輸入、輸出、有窮、確定、可行
	1.2	資料結構分類
		1.2.1	邏輯結構:集合、線性、樹形、圖形
		1.2.2	物理結構:順序儲存、鏈式儲存
2	動態陣列實現
	2.1	設計
		2.1.1	struct dynamicArray
		2.1.2	屬性:  
		2.1.3	void ** pAddr 維護真實在堆區建立的陣列的指標
		2.1.4	int m_capacity; 陣列容量
		2.1.5	int m_size; 陣列大小
	2.2	動態陣列初始化
		2.2.1	struct dynamicArray * init_DynamicArray(int capacity)
	2.3	插入陣列
		2.3.1	void insert_DynamicArray(struct dynamicArray * array , int pos  , void * data)
	2.4	遍歷陣列
		2.4.1	void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
	2.5	刪除陣列
		2.5.1	按照位置刪除  
		2.5.2	void removeByPos_DynamicArray(struct dynamicArray * array , int pos)
		2.5.3	按照值刪除
		2.5.4	void removeByValue_DynamicArray(struct dynamicArray * array , void * data , int (* myCompare)(void * ,void *))
	2.6	銷燬陣列
		2.6.1	void destroy_DynamicArray(struct dynamicArray* array)
	2.7	實現分檔案編寫
3	單向連結串列
	3.1	設計   
		3.1.1	struct LinkNode  節點結構體
		3.1.2	struct LList      連結串列結構體
		3.1.3	typedef  void *  LinkList  給使用者使用連結串列指標
	3.2	初始化連結串列
		3.2.1	LinkList init_LinkList()
	3.3	插入連結串列
		3.3.1	void insert_LinkList(LinkList list, int pos, void * data)
	3.4	遍歷連結串列
		3.4.1	void foreach_LinkList(LinkList list, void(*myForeach)(void *))
	3.5	刪除連結串列
		3.5.1	按照位置void removeByPos_LinkList(LinkList list, int pos)
		3.5.2	按照值void removeByValue_LinkList(LinkList list , void * data ,  int(*myCompare)(void * ,void *) )
	3.6	清空
		3.6.1	void clear_LinkList(LinkList list)
	3.7	返回連結串列長度
		3.7.1	int  size_LinkList(LinkList list)
	3.8	銷燬
		3.8.1	void destroy_Linklist(LinkList list)
4	

Code

動態陣列

  • 標頭檔案 -- dynamicArray.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


//動態陣列結構體
struct dynamicArray
{
	void ** pAddr; //維護真實在堆區建立的陣列的指標

	int m_capacity;  // 陣列容量

	int m_size;   //陣列大小
};

//初始化陣列
struct dynamicArray * init_DynamicArray(int capacity);

//插入陣列
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data);


//遍歷陣列
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*));


//刪除陣列  按位置刪除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos);

//按值刪除資料
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *));


//銷燬陣列
void destroy_DynamicArray(struct dynamicArray* array);
  • 原始檔--dynamicArray.c
#include "dynamicArray.h"


//初始化陣列
struct dynamicArray * init_DynamicArray(int capacity)
{
	if (capacity <= 0)
	{
		return NULL;
	}

	//給陣列分配空間

	struct dynamicArray * array = malloc(sizeof(struct dynamicArray));
	if (array == NULL)
	{
		return NULL;
	}

	//給陣列初始化
	array->pAddr = malloc(sizeof(void *)* capacity);
	array->m_capacity = capacity;
	array->m_size = 0;

	return array;
}

//插入陣列
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data)
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	//無效位置  尾插
	if (pos < 0 || pos > array->m_size)
	{
		pos = array->m_size;
	}

	//判斷是否滿了,如果滿動態擴充套件
	if (array->m_size == array->m_capacity)
	{
		//1、計算新空間大小
		int newCapacity = array->m_capacity * 2;

		//2、建立新空間
		void ** newSpace = malloc(sizeof(void *)* newCapacity);

		//3、將原有資料拷貝到新空間下
		memcpy(newSpace, array->pAddr, sizeof(void *)* array->m_capacity);

		//4、釋放原有記憶體空間
		free(array->pAddr);

		//5、更新新空間指向
		array->pAddr = newSpace;

		//6、更新新容量
		array->m_capacity = newCapacity;
	}

	//插入新元素

	//移動元素 進行插入新元素
	for (int i = array->m_size - 1; i >= pos; i--)
	{
		//資料向後移動
		array->pAddr[i + 1] = array->pAddr[i];
	}

	//將新元素 插入到指定位置上
	array->pAddr[pos] = data;
	//更新大小
	array->m_size++;
}


//遍歷陣列
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
{
	if (array == NULL)
	{
		return;
	}
	if (myPrint == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		myPrint(array->pAddr[i]);
	}
}


//刪除陣列  按位置刪除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos)
{
	if (NULL == array)
	{
		return;
	}

	if (pos < 0 || pos > array->m_size - 1)
	{
		return;
	}

	//資料前移
	for (int i = pos; i < array->m_size - 1; i++)
	{
		array->pAddr[i] = array->pAddr[i + 1];
	}

	//更新陣列大小
	array->m_size--;

}

//按值刪除資料
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *))
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		if (myCompare(array->pAddr[i], data))
		{
			//如果找到要刪除的資料,i就是要刪除的具體位置
			removeByPos_DynamicArray(array, i);
			break;
		}
	}

}

//銷燬陣列
void destroy_DynamicArray(struct dynamicArray* array)
{
	if (array == NULL)
	{
		return;
	}

	if (array->pAddr != NULL)
	{
		free(array->pAddr);
		array->pAddr = NULL;
	}


	free(array);
	array = NULL;
}
  • 原始檔--01 動態陣列.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#include "dynamicArray.h"

////動態陣列結構體
//struct dynamicArray
//{
//	void ** pAddr; //維護真實在堆區建立的陣列的指標
//
//	int m_capacity;  // 陣列容量
//
//	int m_size;   //陣列大小
//};
//
//
////初始化陣列
//struct dynamicArray * init_DynamicArray(int capacity)
//{
//	if (capacity <= 0)
//	{
//		return NULL;
//	}
//
//	//給陣列分配空間
//
//	struct dynamicArray * array  = malloc(sizeof(struct dynamicArray));
//	if (array == NULL)
//	{
//		return NULL;
//	}
//
//	//給陣列初始化
//	array->pAddr = malloc(sizeof(void *)* capacity);
//	array->m_capacity = capacity;
//	array->m_size = 0;
//	
//	return array;
//}
//
////插入陣列
//void insert_DynamicArray(struct dynamicArray * array , int pos  , void * data)
//{
//	if ( array == NULL)
//	{
//		return;
//	}
//	if ( data == NULL)
//	{
//		return;
//	}
//
//	//無效位置  尾插
//	if (pos < 0 || pos > array->m_size)
//	{
//		pos = array->m_size;
//	}
//
//	//判斷是否滿了,如果滿動態擴充套件
//	if (array->m_size == array->m_capacity)
//	{
//		//1、計算新空間大小
//		int newCapacity = array->m_capacity * 2;
//
//		//2、建立新空間
//		void ** newSpace = malloc(sizeof(void *)* newCapacity);
//
//		//3、將原有資料拷貝到新空間下
//		memcpy(newSpace, array->pAddr, sizeof(void *)* array->m_capacity);
//
//		//4、釋放原有記憶體空間
//		free(array->pAddr);
//
//		//5、更新新空間指向
//		array->pAddr = newSpace;
//
//		//6、更新新容量
//		array->m_capacity = newCapacity;
//	}
//
//	//插入新元素
//
//	//移動元素 進行插入新元素
//	for (int i = array->m_size - 1; i >= pos; i--)
//	{
//		//資料向後移動
//		array->pAddr[i + 1] = array->pAddr[i];
//	}
//
//	//將新元素 插入到指定位置上
//	array->pAddr[pos] = data;
//	//更新大小
//	array->m_size++;
//}
//
//
////遍歷陣列
//void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
//{
//	if (array == NULL)
//	{
//		return;
//	}
//	if (myPrint == NULL)
//	{
//		return;
//	}
//
//	for (int i = 0; i < array->m_size;i++)
//	{
//		myPrint(array->pAddr[i]);
//	}
//}
//
//
////刪除陣列  按位置刪除
//void removeByPos_DynamicArray(struct dynamicArray * array , int pos)
//{
//	if ( NULL == array)
//	{
//		return;
//	}
//
//	if (pos < 0  || pos > array->m_size - 1)
//	{
//		return;
//	}
//
//	//資料前移
//	for (int i = pos; i < array->m_size - 1;i++)
//	{
//		array->pAddr[i] = array->pAddr[i + 1];
//	}
//
//	//更新陣列大小
//	array->m_size--;
//
//}
//
////按值刪除資料
//void removeByValue_DynamicArray(struct dynamicArray * array , void * data , int (* myCompare)(void * ,void *))
//{
//	if ( array == NULL)
//	{
//		return;
//	}
//	if ( data == NULL)
//	{
//		return;
//	}
//
//	for (int i = 0; i < array->m_size;i++)
//	{
//		if (myCompare(array->pAddr[i], data))
//		{
//				//如果找到要刪除的資料,i就是要刪除的具體位置
//			removeByPos_DynamicArray(array, i);
//			break;
//		}
//	}
//
//}
//
////銷燬陣列
//void destroy_DynamicArray(struct dynamicArray* array)
//{
//	if (array == NULL)
//	{
//		return;
//	}
//
//	if (array->pAddr != NULL)
//	{
//		free(array->pAddr);
//		array->pAddr = NULL;
//	}
//
//
//	free(array);
//	array = NULL;
//}
//







//測試
struct Person
{
	char name[64];
	int age;
};


void myPrintPerson(void *data)
{
	struct Person * p = data;
	printf("姓名: %s 年齡:%d\n", p->name, p->age);

}

int myComparePerson(void * data1, void *data2)
{
	struct Person *  p1 = data1;
	struct Person *  p2 = data2;

	return  strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}

int main(){

	//初始化動態陣列
	struct dynamicArray * array = init_DynamicArray(5);

	//準備資料
	struct Person p1 = { "亞瑟", 18 };
	struct Person p2 = { "妲己", 20 };
	struct Person p3 = { "安琪拉", 19 };
	struct Person p4 = { "凱", 21 };
	struct Person p5 = { "孫悟空", 999 };
	struct Person p6 = { "李白", 999};

	printf("插入資料前: 容量:%d  大小:%d\n", array->m_capacity, array->m_size);

	//插入資料
	insert_DynamicArray(array, 0, &p1);
	insert_DynamicArray(array, 0, &p2);
	insert_DynamicArray(array, 1, &p3);
	insert_DynamicArray(array, 0, &p4);
	insert_DynamicArray(array, -1, &p5);
	insert_DynamicArray(array, 2, &p6);

	// 凱 妲己 李白 安琪拉  亞瑟  孫悟空

	//遍歷資料
	foreach_DynamicArray(array, myPrintPerson);


	printf("插入資料後: 容量:%d  大小:%d\n", array->m_capacity, array->m_size);


	//測試刪除 按位置刪除
	removeByPos_DynamicArray(array, 2);
	printf("---------------------\n");
	foreach_DynamicArray(array, myPrintPerson);
	printf("刪除資料後: 容量:%d  大小:%d\n", array->m_capacity, array->m_size);

	struct Person  p = { "亞瑟", 18 };
	removeByValue_DynamicArray(array, &p, myComparePerson);
	printf("---------------------\n");
	foreach_DynamicArray(array, myPrintPerson);
	printf("刪除資料後: 容量:%d  大小:%d\n", array->m_capacity, array->m_size);


	//array->pAddr = NULL;
	//array->m_capacity = 0;
	//array->m_size = 0;

	//銷燬陣列
	destroy_DynamicArray(array);
	array = NULL;

	system("pause");
	return EXIT_SUCCESS;
}

單向連結串列

  • 02 單向連結串列.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//節點結構體
struct LinkNode
{
	//資料域
	void * data;
	//指標域
	struct LinkNode * next;
};

//連結串列結構體
struct LList
{
	//頭節點
	struct LinkNode pHeader;
	//連結串列長度
	int m_size;
};

typedef void * LinkList;


//初始化連結串列
LinkList init_LinkList()
{
	 struct LList * myList = malloc(sizeof(struct LList));

	 if (myList == NULL)
	 {
		 return NULL;
	 }

	 myList->pHeader.data = NULL;
	 myList->pHeader.next = NULL;
	 myList->m_size = 0;

	 return myList;
}

//插入連結串列
void insert_LinkList(LinkList list, int pos, void * data)
{
	if (list == NULL)
	{
		return;
	}
	if ( data == NULL)
	{
		return;
	}
	//將list還原成 struct LList資料型別
	struct LList * myList = list;
	if (pos < 0 || pos >myList->m_size)
	{
		//無效位置 強制做尾插
		pos = myList->m_size;
	}

	//找到插入節點的前驅節點位置
	struct LinkNode * pCurrent = &myList->pHeader;

	for (int i = 0; i < pos;i++)
	{
		pCurrent = pCurrent->next;
	}
	//pCurrent 要插入節點的前驅

	//建立新節點

    struct LinkNode * newNode = malloc(sizeof(struct LinkNode));
	newNode->data = data;
	newNode->next = NULL;

	//建立節點關係
	newNode->next = pCurrent->next;
	pCurrent->next = newNode;

	//更新連結串列長度
	myList->m_size++;

}

//遍歷連結串列
void foreach_LinkList(LinkList list, void(*myForeach)(void *))
{
	if (list ==NULL)
	{
		return;
	}

	struct LList * mylist = list;

	struct LinkNode* pCurrent = mylist->pHeader.next;

	for (int i = 0; i < mylist->m_size;i++)
	{
		myForeach(pCurrent->data);
		pCurrent = pCurrent->next;
	}

}


//刪除連結串列  按位置
void removeByPos_LinkList(LinkList list, int pos)
{
	if ( list == NULL)
	{
		return;
	}

	struct LList * mylist = list;

	if (pos < 0 || pos > mylist->m_size - 1)
	{
		return;
	}

	//找到待刪除節點的前驅節點
	struct LinkNode * pCurrent = &mylist->pHeader;
	for (int i = 0; i < pos;i++)
	{
		pCurrent = pCurrent->next;
	}

	//記錄待刪除的節點
	struct LinkNode * pDel = pCurrent->next;

	//重新建立節點關係
	pCurrent->next = pDel->next;

	free(pDel);
	pDel = NULL;

	//更新連結串列長度
	mylist->m_size--;
}

//按照值刪除連結串列
void removeByValue_LinkList(LinkList list , void * data ,  int(*myCompare)(void * ,void *) )
{
	if (list == NULL)
	{
		return;
	}
	if ( data == NULL)
	{
		return;
	}

	struct LList * mylist = list;
	//建立兩個輔助指標
	struct LinkNode * pPrev = &mylist->pHeader;
	struct LinkNode * pCurrent = pPrev->next;

	for (int i = 0; i < mylist->m_size;i++)
	{
		//pCurrent->data  data 將兩個指標比較利用回撥 交給使用者
		if (myCompare (pCurrent->data,data))
		{
			pPrev->next = pCurrent->next;

			free(pCurrent);
			pCurrent = NULL;

			mylist->m_size--;
			break;
		}

		//輔助指標後移
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}
}

//清空連結串列
void clear_LinkList(LinkList list)
{
	if (list == NULL)
	{
		return;
	}

	struct LList * mylist = list;

	struct LinkNode * pCurrent = mylist->pHeader.next;

	for (int i = 0; i < mylist->m_size;i++)
	{
		struct LinkNode * pNext = pCurrent->next;

		free(pCurrent);

		pCurrent = pNext;
	}

	mylist->pHeader.next = NULL;
	mylist->m_size = 0;

}

//返回連結串列長度
int  size_LinkList(LinkList list)
{
	if (list == NULL)
	{
		return -1;
	}

	struct LList * mylist = list;

	return mylist->m_size;
}

//銷燬連結串列
void destroy_Linklist(LinkList list)
{
	if (list == NULL)
	{
		return ;
	}

	//清空連結串列
	clear_LinkList(list);

	free(list);

	list = NULL;

}




//測試 
struct Person
{
	char name[64];
	int age;
};

void myPrintPerson(void * data)
{
	struct Person * p = data;
	printf("姓名:%s  年齡:%d\n", p->name, p->age);
}

int myComparePerson(void * data1, void *data2)
{
	struct Person * p1 = data1;
	struct Person * p2 = data2;

	return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}

void test01()
{
	//準備資料
	struct Person p1 = { "亞瑟", 18 };
	struct Person p2 = { "妲己", 20 };
	struct Person p3 = { "安琪拉", 19 };
	struct Person p4 = { "凱", 21 };
	struct Person p5 = { "孫悟空", 999 };
	struct Person p6 = { "李白", 999 };

	//初始化連結串列
	LinkList mylist = init_LinkList();

	printf("連結串列長度為:%d\n", size_LinkList(mylist));

	//插入資料
	insert_LinkList(mylist, 0, &p1);
	insert_LinkList(mylist, 0, &p2);
	insert_LinkList(mylist, -1, &p3);
	insert_LinkList(mylist, 0, &p4);
	insert_LinkList(mylist, 1, &p5);
	insert_LinkList(mylist, 0, &p6);



	// 李白 凱 孫悟空 妲己 亞瑟 安琪拉

	//遍歷
	foreach_LinkList(mylist, myPrintPerson);

	printf("連結串列長度為:%d\n", size_LinkList(mylist));

	//測試刪除 
	removeByPos_LinkList(mylist, 4);

	printf("------------------\n");

	foreach_LinkList(mylist, myPrintPerson);
	printf("連結串列長度為:%d\n", size_LinkList(mylist));

	struct Person p = { "孫悟空", 999 };
	removeByValue_LinkList(mylist, &p, myComparePerson);

	printf("------------------\n");

	foreach_LinkList(mylist, myPrintPerson);
	printf("連結串列長度為:%d\n", size_LinkList(mylist));

	//測試清空
	clear_LinkList(mylist);

	//返回連結串列長度
	printf("連結串列長度為:%d\n", size_LinkList(mylist));

	//銷燬
	destroy_Linklist(mylist);
	mylist = NULL;
}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

Day02

筆記

1	單向連結串列-企業版
	1.1	設計:節點只維護指標域,使用者資料預留前4個位元組由底層使用
	1.2	介面:
		1.2.1	初始化連結串列
		1.2.2	插入連結串列
		1.2.3	遍歷連結串列
		1.2.4	刪除連結串列
		1.2.5	銷燬連結串列
2	棧的基本概念
	2.1	棧符合 先進後出的資料結構
	2.2	入棧  push
	2.3	出棧  pop
	2.4	棧頂  top
	2.5	棧大小  size
	2.6	是否為空  isEmpty
	2.7	棧底  --- 高地址    棧頂 ---  低地址
	2.8	棧是否可以遍歷 ---- 不可以
3	棧的順序儲存
	3.1	利用陣列模擬出 先進後出資料結構
	3.2	陣列中首地址  做棧底 方便陣列尾部做插入刪除
	3.3	對外介面
		3.3.1	初始化棧 init
		3.3.2	入棧  push
		3.3.3	出棧  pop
		3.3.4	棧頂  top
		3.3.5	棧大小  size
		3.3.6	是否為空  isEmpty
		3.3.7	銷燬棧 destroy
4	棧的鏈式儲存
	4.1	利用連結串列模擬出  先進後出的資料結構
	4.2	頭節點端做棧頂 比較方便做入棧和出棧
	4.3	對外介面
		4.3.1	初始化棧 init
		4.3.2	入棧  push
		4.3.3	出棧  pop
		4.3.4	棧頂  top
		4.3.5	棧大小  size
		4.3.6	是否為空  isEmpty
		4.3.7	銷燬棧 destroy
	4.4	測試
5	棧的應用案例-就近匹配
	5.1	從第一個字元開始掃描所有字元
	5.2	遇到普通字元  直接忽略
	5.3	遇到左括號,入棧
	5.4	遇到右括號
		5.4.1	如果棧中有元素   出棧
		5.4.2	如果棧中沒有元素   立即停止,並且報錯
	5.5	當所有字元都掃描完畢,檢視棧中內容
		5.5.1	如果是空棧,沒有問題
		5.5.2	如果不是空棧,報錯


6	中綴表示式轉字尾表示式
遍歷中綴表示式中的數字和符號:
		對於數字:直接輸出
		對於符號:
			左括號:進棧  
			運算子號:與棧頂符號進行優先順序比較
		若棧頂符號優先順序低:此符號進棧  
		(預設棧頂若是左括號,左括號優先順序最低)
		若棧頂符號優先順序不低:將棧頂符號彈出並輸出,之後進棧
		右括號:將棧頂符號彈出並輸出,直到匹配左括號,將左括號和右括號同時捨棄
	遍歷結束:將棧中的所有符號彈出並輸出


7	基於字尾表示式運算
	遍歷字尾表示式中的數字和符號
		對於數字:進棧
		對於符號:
			從棧中彈出右運算元
			從棧中彈出左運算元
			根據符號進行運算
			將運算結果壓入棧中
	遍歷結束:棧中的唯一數字為計算結果
8	

Code

  • 01 單向連結串列-企業版.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//節點結構體
struct LinkNode
{
	//只維護指標域
	struct LinkNode*next;
};

//連結串列結構體
struct LList
{
	struct LinkNode pHeader;
	int m_Size;
};

typedef void * LinkList;

//初始化連結串列
LinkList init_LinkList()
{
	struct LList * myList = malloc(sizeof(struct LList));

	if (myList == NULL)
	{
		return NULL;
	}

	myList->pHeader.next = NULL;
	myList->m_Size = 0;

	return myList;
}

//插入
void insert_LinkList(LinkList list ,  int pos , void * data)
{
	if (list == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct LList * myList = list;
	if (pos < 0 || pos >myList->m_Size - 1)
	{
		//無效位置進行尾插
		pos = myList->m_Size;
	}

	//使用者資料前4個位元組 由我們來使用
	struct LinkNode * myNode = data;

	//找插入節點的前驅節點
	struct LinkNode * pCurrent = &myList->pHeader;

	for (int i = 0; i < pos;i++)
	{
		pCurrent = pCurrent->next;
	}
	//pCurrent是前驅節點位置


	//更改指標指向
	myNode->next = pCurrent->next;
	pCurrent->next = myNode;

	//更新連結串列長度
	myList->m_Size++;
}

//遍歷連結串列
void foreach_LinkList(LinkList list, void(*myForeach)(void *))
{
	if (list == NULL)
	{
		return;
	}

	struct LList * myList = list;

	struct LinkNode * myNode = myList->pHeader.next;

	for (int i = 0; i < myList->m_Size;i++)
	{
		myForeach(myNode);
		myNode = myNode->next;
	}

}

//刪除節點 按位置刪除
void removeByPos_ListList( LinkList list, int pos)
{
	if (list == NULL)
	{
		return;
	}

	struct LList * mylist = list;

	if (pos < 0 ||  pos > mylist->m_Size - 1)
	{
		return;
	}

	//找待刪除節點的前驅位置
	struct LinkNode * pCurrent = &mylist->pHeader;
	for (int i = 0; i < pos;i++)
	{
		pCurrent = pCurrent->next;
	}

	//記錄待刪除節點
	struct LinkNode * pDel = pCurrent->next;


	//更改指標指向
	pCurrent->next = pDel->next;

	//free(pDel); //資料是使用者管理開闢的,使用者管理釋放

	//更新長度
	mylist->m_Size--;
}

//銷燬陣列
void destroy_LinkList( LinkList list)
{
	if (list == NULL)
	{
		return;
	}

	free(list);
	list = NULL;

}






//測試

struct Person
{
	void * node;
	char name[64];
	int age;
};


void myPrintPerson(void * data)
{
	struct Person * p = data;
	printf("姓名: %s  年齡: %d \n", p->name, p->age);
}

void test01()
{

	//初始化連結串列
	LinkList mylist = init_LinkList();

	//建立資料
	struct Person p1 = { NULL,"aaa", 10 };
	struct Person p2 = { NULL,"bbb", 20 };
	struct Person p3 = { NULL,"ccc", 30 };
	struct Person p4 = { NULL,"ddd", 40 };
	struct Person p5 = { NULL,"eee", 50 };

	//插入節點
	insert_LinkList(mylist, 0, &p1);
	insert_LinkList(mylist, 0, &p2);
	insert_LinkList(mylist, 1, &p3);
	insert_LinkList(mylist, -1, &p4);
	insert_LinkList(mylist, 0, &p5);


	//遍歷連結串列
	// eee bbb  ccc aaa ddd
	foreach_LinkList(mylist, myPrintPerson);

	//刪除 aaa
	removeByPos_ListList(mylist, 3);
	printf("-----------------------\n");
	foreach_LinkList(mylist, myPrintPerson);

	//銷燬陣列
	destroy_LinkList(mylist);
	mylist = NULL;

}


int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

02 棧的順序儲存

  • 標頭檔案 -- seqStack.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define  MAX 1024

//struct SStack
//{
//	void * data[MAX];  //棧的陣列
//
//	int m_Size; //棧大小
//};

typedef void * SeqStack;

//初始化棧
SeqStack init_SeqStack();

//入棧
void push_SeqStack(SeqStack stack, void * data);

//出棧
void pop_SeqStack(SeqStack stack);

//返回棧頂
void * top_SeqStack(SeqStack stack);

//返回棧大小
int size_SeqStack(SeqStack stack);

//判斷棧是否為空
int isEmpty_SeqStack(SeqStack stack);

//銷燬棧
void destroy_SeqStack(SeqStack stack);
  • 原始檔--seqStack.c
#include "seqStack.h"

struct SStack
{
	void * data[MAX];  //棧的陣列

	int m_Size; //棧大小
};

//初始化棧
SeqStack init_SeqStack()
{
	struct SStack * myStack = malloc(sizeof(struct SStack));

	if (myStack == NULL)
	{
		return NULL;
	}

	//初始化陣列
	memset(myStack->data, 0, sizeof(void *)* MAX);

	//初始化棧大小
	myStack->m_Size = 0;

	return myStack;
}
//入棧
void push_SeqStack(SeqStack stack, void * data)
{
	//入棧本質  --- 陣列尾插
	if (stack == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;
	if (mystack->m_Size == MAX)
	{
		return;
	}

	mystack->data[mystack->m_Size] = data;

	mystack->m_Size++;
}
//出棧
void pop_SeqStack(SeqStack stack)
{
	//出棧本質  --- 陣列尾刪
	if (stack == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return;
	}

	mystack->data[mystack->m_Size - 1] = NULL;

	mystack->m_Size--;

}
//返回棧頂
void * top_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return NULL;
	}
	return mystack->data[mystack->m_Size - 1];
}
//返回棧大小
int size_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}

	struct SStack * mystack = stack;

	return mystack->m_Size;

}
//判斷棧是否為空
int isEmpty_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;//返回-1代表真  空棧
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return 1;
	}

	return 0; //返回0 代表 不是空棧

}
//銷燬棧
void destroy_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return;
	}

	free(stack);
	stack = NULL;
}
  • 原始檔--02 棧的順序儲存.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "seqStack.h"


//#define  MAX 1024
//
//struct SStack
//{
//	void * data[MAX];  //棧的陣列
//
//	int m_Size; //棧大小
//};
//
//typedef void * SeqStack;
//
////初始化棧
//SeqStack init_SeqStack()
//{
//	struct SStack * myStack = malloc(sizeof(struct SStack));
//
//	if (myStack == NULL)
//	{
//		return NULL;
//	}
//
//	//初始化陣列
//	memset(myStack->data, 0, sizeof(void *)* MAX);
//
//	//初始化棧大小
//	myStack->m_Size = 0;
//
//	return myStack;
//}
////入棧
//void push_SeqStack(SeqStack stack , void * data)
//{
//	//入棧本質  --- 陣列尾插
//	if (stack == NULL)
//	{
//		return;
//	}
//	if ( data == NULL)
//	{
//		return;
//	}
//
//	struct SStack * mystack = stack;
//	if (mystack->m_Size == MAX)
//	{
//		return;
//	}
//
//	mystack->data[mystack->m_Size] = data;
//
//	mystack->m_Size++;
//}
////出棧
//void pop_SeqStack(SeqStack stack)
//{
//	//出棧本質  --- 陣列尾刪
//	if (stack == NULL)
//	{
//		return;
//	}
//
//	struct SStack * mystack = stack;
//
//	if (mystack->m_Size == 0)
//	{
//		return;
//	}
//
//	mystack->data[mystack->m_Size - 1] = NULL;
//
//	mystack->m_Size--;
//
//}
////返回棧頂
//void * top_SeqStack(SeqStack stack)
//{
//	if (stack == NULL)
//	{
//		return NULL;
//	}
//
//	struct SStack * mystack = stack;
//
//	if (mystack->m_Size == 0)
//	{
//		return NULL;
//	}
//	return mystack->data[mystack->m_Size - 1];
//}
////返回棧大小
//int size_SeqStack(SeqStack stack)
//{
//	if (stack == NULL)
//	{
//		return -1;
//	}
//
//	struct SStack * mystack = stack;
//
//	return mystack->m_Size;
//
//}
////判斷棧是否為空
//int isEmpty_SeqStack(SeqStack stack)
//{
//	if (stack == NULL)
//	{
//		return -1;//返回-1代表真  空棧
//	}
//
//	struct SStack * mystack = stack;
//
//	if (mystack->m_Size == 0)
//	{
//		return 1;
//	}
//
//	return 0; //返回0 代表 不是空棧
//
//}
////銷燬棧
//void destroy_SeqStack(SeqStack stack)
//{
//	if (stack == NULL)
//	{
//		return;
//	}
//
//	free(stack);
//	stack = NULL;
//}





struct Person
{
	char name[64];
	int age;
};

void test01()
{
	//初始化棧
	SeqStack myStack = init_SeqStack();

	//建立資料
	struct Person p1 = {  "aaa", 10 };
	struct Person p2 = {  "bbb", 20 };
	struct Person p3 = {  "ccc", 30 };
	struct Person p4 = {  "ddd", 40 };
	struct Person p5 = {  "eee", 50 };

	//入棧
	push_SeqStack(myStack, &p1);
	push_SeqStack(myStack, &p2);
	push_SeqStack(myStack, &p3);
	push_SeqStack(myStack, &p4);
	push_SeqStack(myStack, &p5);

	printf("棧的元素個數為:%d\n", size_SeqStack(myStack));

	while (isEmpty_SeqStack(myStack) == 0) //棧不為空,檢視棧頂元素,出棧
	{
		struct Person * p = top_SeqStack(myStack);
		printf("姓名:%s 年齡:%d\n", p->name, p->age);

		//出棧
		pop_SeqStack(myStack);
	}

	printf("棧的元素個數為:%d\n", size_SeqStack(myStack));

	//銷燬棧
	destroy_SeqStack(myStack);
}

int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

03 棧的鏈式儲存.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//節點結構體
struct stackNode
{
	struct stackNode * next;
};

//棧的結構體
struct LStack
{
	struct stackNode  pHeader;
	int m_size;
};

typedef void * LinkStack;

//初始化
LinkStack init_LinkStack()
{
	struct LStack * myStack = malloc(sizeof( struct LStack));

	if (myStack == NULL)
	{
		return NULL;
	}
	myStack->pHeader.next = NULL;
	myStack->m_size = 0;

	return myStack;
}
//入棧
void push_LinkStack( LinkStack stack , void * data)
{
	//入棧本質 --- 連結串列頭插
	if (stack == NULL)
	{
		return;
	}

	if (data == NULL)
	{
		return;
	}

	struct LStack * myStack = stack;

	//將使用者資料 取出前4位元組用
	struct stackNode * myNode = data;

	//更改指標指向
	myNode->next = myStack->pHeader.next;
	myStack->pHeader.next = myNode;

	//更新連結串列長度
	myStack->m_size++;

}

//出棧
void pop_LinkStack(LinkStack stack)
{
	//出棧本質 --- 連結串列頭刪
	if (stack == NULL)
	{
		return;
	}

	struct LStack * myStack = stack;

	if (myStack->m_size == 0)
	{
		return;
	}

	//更改指標指向
	//快取第一個有資料節點
	struct stackNode * pFirst = myStack->pHeader.next;

	myStack->pHeader.next = pFirst->next;

	//更新棧大小
	myStack->m_size--;

}

//返回棧頂元素
void * top_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}
	struct LStack * myStack = stack;

	if (myStack->m_size == 0)
	{
		return NULL;
	}

	return myStack->pHeader.next;

}

//返回棧個數
int size_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}
	struct LStack * myStack = stack;

	return myStack->m_size;
}

//判斷是否為空
int isEmpty_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}
	struct LStack * myStack = stack;

	if (myStack->m_size == 0)
	{
		return 1;
	}

	return 0;
}
//銷燬
void destroy_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return;
	}
	free(stack);
	stack = NULL;
}




//測試
struct Person
{
	void * node;
	char name[64];
	int age;
};

void test01()
{
	//初始化棧
	LinkStack myStack = init_LinkStack();

	//建立資料
	struct Person p1 = { NULL, "aaa", 10 };
	struct Person p2 = { NULL, "bbb", 20 };
	struct Person p3 = { NULL, "ccc", 30 };
	struct Person p4 = { NULL, "ddd", 40 };
	struct Person p5 = { NULL, "eee", 50 };

	//入棧
	push_LinkStack(myStack, &p1);
	push_LinkStack(myStack, &p2);
	push_LinkStack(myStack, &p3);
	push_LinkStack(myStack, &p4);
	push_LinkStack(myStack, &p5);

	printf("鏈式儲存-- 棧的元素個數為:%d\n", size_LinkStack(myStack));

	while (isEmpty_LinkStack(myStack) == 0) //棧不為空,檢視棧頂元素,出棧
	{
		struct Person * p = top_LinkStack(myStack);
		printf("姓名:%s 年齡:%d\n", p->name, p->age);

		//出棧
		pop_LinkStack(myStack);
	}

	printf("鏈式儲存-- 棧的元素個數為:%d\n", size_LinkStack(myStack));

	//銷燬棧
	destroy_LinkStack(myStack);
}
int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

04 棧的應用案例(就近匹配).c

  • 標頭檔案-- seqStack.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define  MAX 1024

//struct SStack
//{
//	void * data[MAX];  //棧的陣列
//
//	int m_Size; //棧大小
//};

typedef void * SeqStack;

//初始化棧
SeqStack init_SeqStack();

//入棧
void push_SeqStack(SeqStack stack, void * data);

//出棧
void pop_SeqStack(SeqStack stack);

//返回棧頂
void * top_SeqStack(SeqStack stack);

//返回棧大小
int size_SeqStack(SeqStack stack);

//判斷棧是否為空
int isEmpty_SeqStack(SeqStack stack);

//銷燬棧
void destroy_SeqStack(SeqStack stack);
  • 原始檔--seqStack.c
#include "seqStack.h"

struct SStack
{
	void * data[MAX];  //棧的陣列

	int m_Size; //棧大小
};

//初始化棧
SeqStack init_SeqStack()
{
	struct SStack * myStack = malloc(sizeof(struct SStack));

	if (myStack == NULL)
	{
		return NULL;
	}

	//初始化陣列
	memset(myStack->data, 0, sizeof(void *)* MAX);

	//初始化棧大小
	myStack->m_Size = 0;

	return myStack;
}
//入棧
void push_SeqStack(SeqStack stack, void * data)
{
	//入棧本質  --- 陣列尾插
	if (stack == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;
	if (mystack->m_Size == MAX)
	{
		return;
	}

	mystack->data[mystack->m_Size] = data;

	mystack->m_Size++;
}
//出棧
void pop_SeqStack(SeqStack stack)
{
	//出棧本質  --- 陣列尾刪
	if (stack == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return;
	}

	mystack->data[mystack->m_Size - 1] = NULL;

	mystack->m_Size--;

}
//返回棧頂
void * top_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return NULL;
	}
	return mystack->data[mystack->m_Size - 1];
}
//返回棧大小
int size_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}

	struct SStack * mystack = stack;

	return mystack->m_Size;

}
//判斷棧是否為空
int isEmpty_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;//返回-1代表真  空棧
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return 1;
	}

	return 0; //返回0 代表 不是空棧

}
//銷燬棧
void destroy_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return;
	}

	free(stack);
	stack = NULL;
}
  • 04 棧的應用案例(就近匹配).c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "seqStack.h"
/*
從第一個字元開始掃描
當遇見普通字元時忽略,
當遇見左括號時壓入棧中
當遇見右括號時從棧中彈出棧頂符號,並進行匹配
匹配成功:繼續讀入下一個字元
匹配失敗:立即停止,並報錯
結束:
成功: 所有字元掃描完畢,且棧為空
失敗:匹配失敗或所有字元掃描完畢但棧非空
*/

int isLeft(char ch)
{
	return ch == '(';
}

int isRight(char ch)
{
	return ch == ')';
}

void printError(char * str, char * errMsg , char * pos)
{
	printf("錯誤資訊:%s\n", errMsg);

	printf("%s\n", str);

	//計算列印空格數量
	int num = pos - str;

	for (int i = 0; i < num;i++)
	{
		printf(" ");
	}
	printf("|\n");
}

void test01()
{

	char * str = "5+5*(6)+9/3*1)-(1+3(";
	//char * str = "5+5*(6)+9/3*1-(1+3(";


	char * p = str;

	//初始化棧
	SeqStack myStack = init_SeqStack();

	while ( *p != '\0')
	{
		//如果是左括號,入棧
		if (isLeft(*p))
		{
			//入棧
			push_SeqStack(myStack, p);
		}

		//如果是右括號 
		if (isRight(*p))
		{
			//棧中有元素   出棧
			if (size_SeqStack(myStack) > 0)
			{
				pop_SeqStack(myStack);
			}
			else
			{
				//右括號沒有匹配到對應的左括號,立即停止,並報錯
				printError(str,"右括號沒有匹配到對應的左括號!", p);
				break;
			}
		}
		p++;
	}

	//遍歷結束 判斷是否有 左括號沒有匹配到對應的右括號
	while (size_SeqStack(myStack) > 0)
	{
		printError(str, "左括號沒有匹配到對應的右括號!", top_SeqStack(myStack));
		//出棧
		pop_SeqStack(myStack);
	}	

	//銷燬棧
	destroy_SeqStack(myStack);
	myStack = NULL;


}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

Day03

Code

01 佇列的順序儲存

標頭檔案

  • dynamicArray.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


//動態陣列結構體
struct dynamicArray
{
	void ** pAddr; //維護真實在堆區建立的陣列的指標

	int m_capacity;  // 陣列容量

	int m_size;   //陣列大小
};

//初始化陣列
struct dynamicArray * init_DynamicArray(int capacity);

//插入陣列
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data);


//遍歷陣列
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*));


//刪除陣列  按位置刪除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos);

//按值刪除資料
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *));


//銷燬陣列
void destroy_DynamicArray(struct dynamicArray* array);
  • seqQueue.h
#pragma  once 
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "dynamicArray.h"
#define  MAX  1024

typedef void * seqQueue;

//初始化佇列
seqQueue init_SeqQueue();
//入隊
void push_SeqQueue(seqQueue queue , void * data);
//出隊
void pop_SeqQueue(seqQueue queue);
//返回佇列大小
int size_SeqQueue(seqQueue queue);
//判斷佇列是否為空
int isEmpty_SeqQueue(seqQueue queue);
//返回隊頭元素
void * front_SeqQueue(seqQueue queue);
//返回隊尾元素
void * back_SeqQueue(seqQueue queue);
//銷燬佇列
void destroy_SeqQueue(seqQueue queue);

原始檔

  • dynamicArray.c
#include "dynamicArray.h"


//初始化陣列
struct dynamicArray * init_DynamicArray(int capacity)
{
	if (capacity <= 0)
	{
		return NULL;
	}

	//給陣列分配空間

	struct dynamicArray * array = malloc(sizeof(struct dynamicArray));
	if (array == NULL)
	{
		return NULL;
	}

	//給陣列初始化
	array->pAddr = malloc(sizeof(void *)* capacity);
	array->m_capacity = capacity;
	array->m_size = 0;

	return array;
}

//插入陣列
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data)
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	//無效位置  尾插
	if (pos < 0 || pos > array->m_size)
	{
		pos = array->m_size;
	}

	//判斷是否滿了,如果滿動態擴充套件
	if (array->m_size == array->m_capacity)
	{
		//1、計算新空間大小
		int newCapacity = array->m_capacity * 2;

		//2、建立新空間
		void ** newSpace = malloc(sizeof(void *)* newCapacity);

		//3、將原有資料拷貝到新空間下
		memcpy(newSpace, array->pAddr, sizeof(void *)* array->m_capacity);

		//4、釋放原有記憶體空間
		free(array->pAddr);

		//5、更新新空間指向
		array->pAddr = newSpace;

		//6、更新新容量
		array->m_capacity = newCapacity;
	}

	//插入新元素

	//移動元素 進行插入新元素
	for (int i = array->m_size - 1; i >= pos; i--)
	{
		//資料向後移動
		array->pAddr[i + 1] = array->pAddr[i];
	}

	//將新元素 插入到指定位置上
	array->pAddr[pos] = data;
	//更新大小
	array->m_size++;
}


//遍歷陣列
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
{
	if (array == NULL)
	{
		return;
	}
	if (myPrint == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		myPrint(array->pAddr[i]);
	}
}


//刪除陣列  按位置刪除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos)
{
	if (NULL == array)
	{
		return;
	}

	if (pos < 0 || pos > array->m_size - 1)
	{
		return;
	}

	//資料前移
	for (int i = pos; i < array->m_size - 1; i++)
	{
		array->pAddr[i] = array->pAddr[i + 1];
	}

	//更新陣列大小
	array->m_size--;

}

//按值刪除資料
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *))
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		if (myCompare(array->pAddr[i], data))
		{
			//如果找到要刪除的資料,i就是要刪除的具體位置
			removeByPos_DynamicArray(array, i);
			break;
		}
	}

}

//銷燬陣列
void destroy_DynamicArray(struct dynamicArray* array)
{
	if (array == NULL)
	{
		return;
	}

	if (array->pAddr != NULL)
	{
		free(array->pAddr);
		array->pAddr = NULL;
	}


	free(array);
	array = NULL;
}
  • seqQueue.c
#include "seqQueue.h"

//初始化佇列
seqQueue init_SeqQueue()
{
	struct dynamicArray * arr = init_DynamicArray(MAX);

	return arr;
}
//入隊
void push_SeqQueue(seqQueue queue, void * data)
{
	//本質  尾插
	
	if (queue == NULL)
	{
		return;
	}
	if ( data == NULL)
	{
		return;
	}
	struct dynamicArray * myQueue = queue;
	if (myQueue->m_size == MAX)
	{
		return;
	}

	insert_DynamicArray(myQueue, myQueue->m_size, data);

}
//出隊
void pop_SeqQueue(seqQueue queue)
{
	//本質  頭刪

	if (queue == NULL)
	{
		return;
	}

	struct dynamicArray * myQueue = queue;

	if (myQueue->m_size <= 0 )
	{
		return;
	}

	removeByPos_DynamicArray(myQueue, 0);

}
//返回佇列大小
int size_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}

	struct dynamicArray * myQueue = queue;

	return myQueue->m_size;

}
//判斷佇列是否為空
int isEmpty_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}
	struct dynamicArray * myQueue = queue;

	if (myQueue->m_size == 0)
	{
		return 1;
	}
	return 0;


}
//返回隊頭元素
void * front_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}
	struct dynamicArray * myQueue = queue;

	return myQueue->pAddr[0];

}
//返回隊尾元素
void * back_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}
	struct dynamicArray * myQueue = queue;

	return myQueue->pAddr[myQueue->m_size-1];
}
//銷燬佇列
void destroy_SeqQueue(seqQueue queue)
{
	if (queue == NULL)
	{
		return;
	}
	
	destroy_DynamicArray(queue);

}
  • 01 佇列的順序儲存.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "seqQueue.h"

struct Person
{
	char name[64];
	int age;
};
void test01()
{
	//初始化佇列
	seqQueue myQueue= init_SeqQueue();

	//準備資料
	struct Person p1 = { "aaa", 10 };
	struct Person p2 = { "bbb", 20 };
	struct Person p3 = { "ccc", 30 };
	struct Person p4 = { "ddd", 40 };


	//入隊
	push_SeqQueue(myQueue, &p1);
	push_SeqQueue(myQueue, &p2);
	push_SeqQueue(myQueue, &p3);
	push_SeqQueue(myQueue, &p4);
	printf("佇列大小為:%d\n", size_SeqQueue(myQueue));
	while ( isEmpty_SeqQueue(myQueue) == 0)
	{
		//訪問隊頭
		struct Person * pFront = front_SeqQueue(myQueue);
		printf("隊頭元素 -- 姓名:%s  年齡: %d\n", pFront->name, pFront->age);
		//訪問隊尾
		struct Person * pBack = back_SeqQueue(myQueue);
		printf("隊尾元素 -- 姓名:%s  年齡: %d\n", pBack->name, pBack->age);
		//出隊
		pop_SeqQueue(myQueue);
	}

	printf("佇列大小為:%d\n", size_SeqQueue(myQueue));

	//銷燬佇列
	destroy_SeqQueue(myQueue);

}



int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

02 佇列的鏈式儲存

標頭檔案

  • linkQueue.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


//節點結構體
struct QueueNode
{
	struct QueueNode * next;
};

//佇列結構體
struct LQueue
{
	struct QueueNode pHeader;
	int m_size;
	struct QueueNode * pTail;
};

typedef void * LinkQueue;

//初始化佇列
LinkQueue init_LinkQueue();
//入隊
void push_LinkQueue(LinkQueue queue , void * data);
//出隊
void pop_LinkQueue(LinkQueue queue);
//返回佇列大小
int size_LinkQueue(LinkQueue queue);
//判斷是否為空
int isEmpty_LinkQueue(LinkQueue queue);
//返回隊頭
void * front_LinkQueue(LinkQueue queue);
//返回隊尾
void * back_LinkQueue(LinkQueue queue);
//銷燬佇列
void destroy_LinkQueue(LinkQueue queue);

原始檔

  • linkQueue.c
#include "linkQueue.h"

//初始化佇列
LinkQueue init_LinkQueue()
{
	 struct LQueue * myQueue = malloc(sizeof(struct  LQueue));

	 if (myQueue == NULL)
	 {
		 return NULL;
	 }

	 myQueue->pHeader.next = NULL;

	 myQueue->m_size = 0;

	 myQueue->pTail = &myQueue->pHeader;

	 return myQueue;
}
//入隊
void push_LinkQueue(LinkQueue queue, void * data)
{
	if (queue == NULL)
	{
		return;
	}
	if ( data == NULL)
	{
		return;
	}

	//本質 尾插
	struct LQueue * myQueue = queue;


	struct QueueNode * myNode = data;

	//更改指標指向
	myQueue->pTail->next = myNode;
	myNode->next = NULL;

	//更新新的尾節點
	myQueue->pTail = myNode;

	myQueue->m_size++;

}
//出隊
void pop_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return;
	}

	struct LQueue * myQueue = queue;

	//本質 頭刪

	if (myQueue->m_size == 0)
	{
		return;
	}

	if (myQueue->m_size == 1)
	{
		myQueue->pHeader.next = NULL;
		myQueue->pTail = &myQueue->pHeader;  //1個節點的時候,要將尾節點還原到頭
		myQueue->m_size--;
		return;
	}

	//記錄第一個有資料的節點
	struct QueueNode * pFirst = myQueue->pHeader.next;

	//更改指標指向
	myQueue->pHeader.next = pFirst->next;

	myQueue->m_size--;

}
//返回佇列大小
int size_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}

	struct LQueue * myQueue = queue;
	return myQueue->m_size;


}
//判斷是否為空
int isEmpty_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}

	struct LQueue * myQueue = queue;
	if (myQueue->m_size == 0)
	{
		return 1;
	}
	return 0;

}
//返回隊頭
void * front_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}

	struct LQueue * myQueue = queue;

	return myQueue->pHeader.next;

}
//返回隊尾
void * back_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}

	struct LQueue * myQueue = queue;
	return myQueue->pTail;
}
//銷燬佇列
void destroy_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return;
	}

	free(queue);
	queue = NULL;

}
  • 02 佇列的鏈式儲存.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "linkQueue.h"

struct Person
{
	void * node;
	char name[64];
	int age;
};
void test01()
{
	//初始化佇列
	LinkQueue myQueue = init_LinkQueue();

	//準備資料
	struct Person p1 = { NULL,"aaa", 10 };
	struct Person p2 = { NULL,"bbb", 20 };
	struct Person p3 = { NULL,"ccc", 30 };
	struct Person p4 = { NULL,"ddd", 40 };


	//入隊
	push_LinkQueue(myQueue, &p1);
	push_LinkQueue(myQueue, &p2);
	push_LinkQueue(myQueue, &p3);
	push_LinkQueue(myQueue, &p4);
	printf("佇列大小為:%d\n", size_LinkQueue(myQueue));
	while (isEmpty_LinkQueue(myQueue) == 0)
	{
		//訪問隊頭
		struct Person * pFront = front_LinkQueue(myQueue);
		printf("鏈式儲存::隊頭元素 -- 姓名:%s  年齡: %d\n", pFront->name, pFront->age);
		//訪問隊尾
		struct Person * pBack = back_LinkQueue(myQueue);
		printf("鏈式儲存::隊尾元素 -- 姓名:%s  年齡: %d\n", pBack->name, pBack->age);
		//出隊
		pop_LinkQueue(myQueue);
	}

	printf("佇列大小為:%d\n", size_LinkQueue(myQueue));

	//銷燬佇列
	destroy_LinkQueue(myQueue);

}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

03 二叉樹的遞迴遍歷.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct BinaryNode
{
	//資料域
	char ch;
	//指標域
	struct BinaryNode * lChild;
	struct BinaryNode * rChild;
};


void recursion(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return;
	}

	//先序遍歷
	printf("%c ", root->ch);

	recursion(root->lChild);

	recursion(root->rChild);

}


void test01()
{
	struct BinaryNode nodeA = { 'A', NULL, NULL };
	struct BinaryNode nodeB = { 'B', NULL, NULL };
	struct BinaryNode nodeC = { 'C', NULL, NULL };
	struct BinaryNode nodeD = { 'D', NULL, NULL };
	struct BinaryNode nodeE = { 'E', NULL, NULL };
	struct BinaryNode nodeF = { 'F', NULL, NULL };
	struct BinaryNode nodeG = { 'G', NULL, NULL };
	struct BinaryNode nodeH = { 'H', NULL, NULL };

	//建立關係
	nodeA.lChild = &nodeB;
	nodeA.rChild = &nodeF;

	nodeB.rChild = &nodeC;
	
	nodeC.lChild = &nodeD;
	nodeC.rChild = &nodeE;

	nodeF.rChild = &nodeG;
	
	nodeG.lChild = &nodeH;

	//遞迴遍歷
	recursion(&nodeA);

}


int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

04 二叉樹程式設計.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct BinaryNode
{
	//資料域
	char ch;
	//指標域
	struct BinaryNode * lChild;
	struct BinaryNode * rChild;
};


void calculateLeafNum(struct BinaryNode * root, int * p)
{
	if (root == NULL)
	{
		return;
	}

	//如果節點 左子樹 與右子樹 同時為空  稱為葉子
	if (root->lChild == NULL && root->rChild == NULL)
	{
		(*p)++;
	}

	calculateLeafNum(root->lChild, p);

	calculateLeafNum(root->rChild, p);

}

//獲取樹高度
int getTreeHeight(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return 0;
	}

	//獲取左子樹高度 
	int  lHeight = getTreeHeight(root->lChild);
	//獲取右子樹高度
	int  rHeight = getTreeHeight(root->rChild);
	//從左子樹和右子樹中取大的值+1
	int height = lHeight > rHeight ? lHeight + 1 : rHeight + 1;

	return height;
}

//拷貝二叉樹
struct BinaryNode * copyTree(struct BinaryNode * root)
{
	if (root ==NULL)
	{
		return NULL;
	}

	//先拷貝左子樹
	struct BinaryNode * lChild = copyTree(root->lChild);
	//再拷貝右子樹
	struct BinaryNode * rChild = copyTree(root->rChild);

	struct BinaryNode * newNode = malloc(sizeof(struct BinaryNode));
	newNode->ch = root->ch;

	newNode->lChild = lChild;

	newNode->rChild = rChild;

	return newNode;
}

void recursion(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return;
	}

	printf("%c ", root->ch);

	recursion(root->lChild);

	recursion(root->rChild);

}


void freeTree(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return;
	}

	//先釋放左子樹
	freeTree(root->lChild);
	//再釋放右子樹
	freeTree(root->rChild);
	//釋放根
	printf("%c被釋放了\n", root->ch);
	free(root);
}

void test01()
{
	struct BinaryNode nodeA = { 'A', NULL, NULL };
	struct BinaryNode nodeB = { 'B', NULL, NULL };
	struct BinaryNode nodeC = { 'C', NULL, NULL };
	struct BinaryNode nodeD = { 'D', NULL, NULL };
	struct BinaryNode nodeE = { 'E', NULL, NULL };
	struct BinaryNode nodeF = { 'F', NULL, NULL };
	struct BinaryNode nodeG = { 'G', NULL, NULL };
	struct BinaryNode nodeH = { 'H', NULL, NULL };

	//建立關係
	nodeA.lChild = &nodeB;
	nodeA.rChild = &nodeF;

	nodeB.rChild = &nodeC;

	nodeC.lChild = &nodeD;
	nodeC.rChild = &nodeE;

	nodeF.rChild = &nodeG;

	nodeG.lChild = &nodeH;

	//1、求二叉樹 葉子數量
	int num = 0;
	calculateLeafNum(&nodeA, &num);

	printf("樹的葉子數量為:%d\n", num);


	//2、 求樹的高度/深度
	int height = getTreeHeight( &nodeA);

	printf("樹的高度為:%d\n", height);


	//3、 拷貝二叉樹
	struct BinaryNode * newTree = copyTree(&nodeA);

	//遞迴遍歷
	recursion(newTree);

	printf("\n");
	//4、 釋放二叉樹
	freeTree(newTree);


}


int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

05 二叉樹非遞迴遍歷

標頭檔案

  • seqStack.h
#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define  MAX 1024

//struct SStack
//{
//	void * data[MAX];  //棧的陣列
//
//	int m_Size; //棧大小
//};

typedef void * SeqStack;

//初始化棧
SeqStack init_SeqStack();

//入棧
void push_SeqStack(SeqStack stack, void * data);

//出棧
void pop_SeqStack(SeqStack stack);

//返回棧頂
void * top_SeqStack(SeqStack stack);

//返回棧大小
int size_SeqStack(SeqStack stack);

//判斷棧是否為空
int isEmpty_SeqStack(SeqStack stack);

//銷燬棧
void destroy_SeqStack(SeqStack stack);

原始檔

  • seqStack.c
#include "seqStack.h"

struct SStack
{
	void * data[MAX];  //棧的陣列

	int m_Size; //棧大小
};

//初始化棧
SeqStack init_SeqStack()
{
	struct SStack * myStack = malloc(sizeof(struct SStack));

	if (myStack == NULL)
	{
		return NULL;
	}

	//初始化陣列
	memset(myStack->data, 0, sizeof(void *)* MAX);

	//初始化棧大小
	myStack->m_Size = 0;

	return myStack;
}
//入棧
void push_SeqStack(SeqStack stack, void * data)
{
	//入棧本質  --- 陣列尾插
	if (stack == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;
	if (mystack->m_Size == MAX)
	{
		return;
	}

	mystack->data[mystack->m_Size] = data;

	mystack->m_Size++;
}
//出棧
void pop_SeqStack(SeqStack stack)
{
	//出棧本質  --- 陣列尾刪
	if (stack == NULL)
	{
		return;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return;
	}

	mystack->data[mystack->m_Size - 1] = NULL;

	mystack->m_Size--;

}
//返回棧頂
void * top_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return NULL;
	}
	return mystack->data[mystack->m_Size - 1];
}
//返回棧大小
int size_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}

	struct SStack * mystack = stack;

	return mystack->m_Size;

}
//判斷棧是否為空
int isEmpty_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;//返回-1代表真  空棧
	}

	struct SStack * mystack = stack;

	if (mystack->m_Size == 0)
	{
		return 1;
	}

	return 0; //返回0 代表 不是空棧

}
//銷燬棧
void destroy_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return;
	}

	free(stack);
	stack = NULL;
}
  • 05 二叉樹非遞迴遍歷.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "seqStack.h"

struct BinaryNode
{
	//資料域
	char ch;
	//指標域
	struct BinaryNode * lChild;
	struct BinaryNode * rChild;
	//標誌
	int flag;
};


/*
1、將根節點 入棧 
2、只要棧中元素個數大於 0  執行迴圈
	獲取棧頂元素
	出棧
	如果標誌位真  直接輸出  並且執行下一次迴圈
	如果為假 將標誌改為真
	將右子樹  左子樹 根 入棧
	執行下一次迴圈
*/

void nonRecursion(struct BinaryNode * root)
{
	//初始化棧
	SeqStack myStack = init_SeqStack();

	push_SeqStack(myStack, root);

	while (size_SeqStack(myStack) > 0)
	{
		//獲取棧頂元素
		struct BinaryNode * pTop = top_SeqStack(myStack);

		//出棧
		pop_SeqStack(myStack);

		//如果標誌位真  直接輸出  並且執行下一次迴圈
		if (pTop->flag == 1)
		{
			printf("%c ", pTop->ch);
			continue;
		}
		//如果為假 將標誌改為真
		pTop->flag = 1;

		//將右子樹  左子樹 根 入棧
		if (pTop->rChild != NULL)
		{
			push_SeqStack(myStack, pTop->rChild);
		}
		if (pTop->lChild != NULL)
		{
			push_SeqStack(myStack, pTop->lChild);
		}
		push_SeqStack(myStack, pTop);

	}

	//銷燬棧
	destroy_SeqStack(myStack);

}

void test01()
{
	struct BinaryNode nodeA = { 'A', NULL, NULL,0 };
	struct BinaryNode nodeB = { 'B', NULL, NULL,0 };
	struct BinaryNode nodeC = { 'C', NULL, NULL,0 };
	struct BinaryNode nodeD = { 'D', NULL, NULL,0 };
	struct BinaryNode nodeE = { 'E', NULL, NULL,0 };
	struct BinaryNode nodeF = { 'F', NULL, NULL,0 };
	struct BinaryNode nodeG = { 'G', NULL, NULL,0 };
	struct BinaryNode nodeH = { 'H', NULL, NULL,0 };

	//建立關係
	nodeA.lChild = &nodeB;
	nodeA.rChild = &nodeF;

	nodeB.rChild = &nodeC;

	nodeC.lChild = &nodeD;
	nodeC.rChild = &nodeE;

	nodeF.rChild = &nodeG;

	nodeG.lChild = &nodeH;

	//非遞迴遍歷
	nonRecursion(&nodeA);

	



}

int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

06 插入排序.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void insertSort(int arr[], int len)
{
	for (int i = 1; i < len;i++)
	{
		if (arr[i-1] > arr[i])
		{
			int temp = arr[i];
			int j = i - 1;
			for (; j >= 0 && temp < arr[j]; j--)
			{
				//資料後移
				arr[j + 1] = arr[j];
			}
			arr[j + 1] = temp;
		}
	}
}

void printArray(int arr[] ,int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%d\n",arr[i]);
	}
}

void test01()
{
	int arr[] = { 4, 1, 2, 3, 5, 7, 6 };
	//插入排序
	int len = sizeof(arr) / sizeof(int);
	insertSort(arr, len);

	//列印陣列
	printArray(arr, len);

}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}