数据结构学习回顾和总结

目录

1.什么是数据结构

 1.2结构

1.2.1逻辑结构:

1.2.2存储结构:

1.3操作

2.常见的数据结构

2.1顺序表

 2.2单链表

2.3栈 

2.4队列 

2.5树


1.什么是数据结构

数据结构:数据(由数据元素组成(一种基本数据类型或者结构体))+结构(逻辑结构+存储结构)+操作(增删改查)

 1.2结构

结构分为逻辑结构和存储结构

1.2.1逻辑结构:

数据元素和数据元素之间的逻辑关系--如线性结构、非线性(树状、图状)结构

1.2.2存储结构:

数据在内存中的存储方式

很多结构变量存放在内存里----如顺序存储(一次性开辟一块很大的空间--数组)、链式存储(内存空间是不连续的,上一个元素可以通过地址找到下一个元素

逻辑结构是线性,存储结构是顺序-----顺序表(数组)

逻辑结构是线性,存储结构是链式-----链表

逻辑结构是树状,存储结构是顺序----树

逻辑结构是树状,存储结构是链式---树

1.3操作

创建、插入、删除、查找、修改、销毁---内存里(不能永久保存)

  1. 操作完之后将内存中的数据保存到文件

启动系统之后将保存在文件中的数据读到内存

2.常见的数据结构

2.1顺序表

顺序存储的线性表----逻辑结构是线性的、存储结构是顺序的

可以高效地存储和访问一对一的数据

特点:

1.顺序表使用一段连续的内存空间来存储数据元素,每个元素占用相同大小的空间,可以通过下标     快速定位元素的位置。

2.顺序表的插入和删除操作需要移动大量的元素,以保持数据的连续性。所以一般不用头部插入和     删除,尾部的插入和删除效率是最高,因为不需要移动任何元素。

应用场景:排序、查找等。

list.c

#include "list.h"


//函数声明
//顺序表创建
List *creat_list()
{
	//给顺序表申请空间,空间有了,但还没元素,空表
	List *pList = (List *)malloc(sizeof(List));
	if(NULL == pList)
	{
		return NULL;
	}
	//数组的元素此时全部都是0,count此时也是0
	memset(pList, 0, sizeof(List));
	return pList;//handle
}


//数据元素插入到顺序表
int insert_item_list(List *pList, int index, data_t tData)
{
	int i;
	//入参检查
	if(index > pList->count || index < 0 || NULL == pList)
	{
		return LIST_ERR;
	}

	//判断表是否满
	if(SIZE == pList->count)
	{
		return LIST_FULL;
	}

	//移动元素将位置腾出来
	for(i = pList->count; i > index; i--)
	{
		pList->data[i] = pList->data[i-1];
	}
	//插入元素
	pList->data[index] = tData; 
	//元素个数增加一个
	pList->count++;
	return LIST_OK;

}
//从顺序表中删除元素
int delete_item_list(List *pList, int index, data_t *pData)
{
	int i;
	if(NULL == pList || index < 0 || index >= pList->count)
	{
		return LIST_ERR;
	}
	//判断表是否为空
	if(0 == pList->count)
	{
		return LIST_EMPTY;
	}

	//保存要删除的元素
	//pData--->dData
	//给main函数中定义的dData赋值
	*pData = pList->data[index];
	//删除对应下标元素
	for(i = index; i < pList->count-1; i++)
	{
		pList->data[i] = pList->data[i+1];
	}
	//元素个数减少一个
	pList->count--;
	return LIST_OK;
}
//修改某个元素的值
int update_item_list(List *pList, int index, data_t newData)
{
	//入参检查
	if( NULL == pList || index < 0 || index > pList->count)
	{
		return LIST_ERR;
	}
 	
	//修改某个元素的值
	pList->data[index] = newData;

	return LIST_OK;
}
//查找某个元素
data_t find_item_list(List *pList, int index,data_t *fData)
{
	//入参检查
	if(NULL == pList || index < 0 || index > pList->count)
	{
		return LIST_ERR;
	}
	//表为空
	if(0 == pList->count)
	{
		return LIST_EMPTY;
	}
	*fData = pList->data[index];
	return LIST_OK;
}
//销毁顺序表
void destroy_list(List **ppList)
{
	if(NULL == ppList || NULL == *ppList)
	{
		return;
	}
	free(*ppList); //free(pList);
	*ppList = NULL;  //ppList-->main中的pList, pList = NULL;
}
//显示顺序表中的内容
void show_list(List *pList)
{
	int i;
	if(NULL == pList)
	{
		return;
	}
	//打印数组元素
    for(i = 0; i < pList->count; i++)
	{
		printf("%d ", pList->data[i]);
	}
	printf("\n");
}









list.h

#ifndef _LIST_H_
#define _LIST_H_


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


enum LIST_OP
{
	LIST_ERR = -1,
	LIST_OK,
	LIST_FULL,
	LIST_EMPTY,
};

//为了更通用
#define SIZE 5
typedef int data_t; //如果下次元素类型是其他类型,只需要改这里就好,不需要改函数中的代码


//定义顺序表的结构体类型
typedef struct List
{
	data_t data[SIZE];
	int count;
} List;


//函数声明
//顺序表创建
List *creat_list();
//数据元素插入到顺序表
int insert_item_list(List *pList, int index, data_t tData);
//从顺序表中删除元素
int delete_item_list(List *pList, int index, data_t *pData);
//修改某个元素的值
int update_item_list(List *pList, int index, data_t newData);
//查找某个元素
data_t find_item_list(List *pList, int index,data_t *fData);
//销毁顺序表
void destroy_list(List **ppList);
//显示顺序表中的内容
void show_list(List *pList);


#endif

 2.2单链表

链表是一种非连续的、非顺序的存储结构,它由一系列节点组成,每个节点包含一个数据域和一个指向下一个节点的指针。

特点:

1.插入和删除操作比较高效,因为只需要修改指针即可。

2.无法实现随机访问,需要从头节点开始遍历才能找到目标元素。

应用场景:栈、队列、哈希表。

link.c

#include "link.h"

//创建一个新的节点
//参数:存放数据元素的结构体
//返回值:节点的首地址
static LinkNode *create_node(data_t tData)
{
	LinkNode *pNode = (LinkNode*)malloc(sizeof(LinkNode));
	if(NULL == pNode)
	{
		return NULL;
	}
	memset(pNode,0,sizeof(LinkNode));
	pNode->data = tData;

	return pNode;
}

//创建一个空的单链表
//返回值单链表的首地址
Link *create_link()
{
	Link *pLink = (Link*)malloc(sizeof(Link));
	if(NULL == pLink)
	{
		return NULL;
	}
	memset(pLink,0,sizeof(Link));
	return pLink;
}

//销毁一个单链表
//参数:单链表的地址
void destroy_link(Link **ppLink)
{
	LinkNode *pDel = (*ppLink)->pHead;
	if(NULL == ppLink | NULL == *ppLink)
	{
		return;
	}

	//不是空表
	if((*ppLink)->count > 0)
	{
		while(pDel != NULL)
		{
			(*ppLink)->pHead = pDel->pNext;
			free(pDel);
			pDel = (*ppLink)->pHead;
		}
	}
	//删除空表
	free(*ppLink);
	*ppLink = NULL;
}

//头部插入
//参数1:单链表
//参数2:存放数据元素的结构体
int push_head_link(Link *pLink,data_t tData)
{
	//入参检查
	if(NULL == pLink)
	{
		return LINK_ERR;
	}
	//创建一个新的节点
	LinkNode *pNode = create_node(tData);
	if(NULL == pNode)
	{
		return LINK_ERR;
	}
	
	//插入
	pNode->pNext = pLink->pHead;
	pLink->pHead = pNode;
	
	//元素个数+1
	pLink->count++;

	return LINK_OK;

}

//尾部插入
//参数1:单链表
//参数2:存放数据元素的结构体
int push_back_link(Link *pLink,data_t tData)
{
	LinkNode *pNode = NULL;
	LinkNode *pTmp = pLink->pHead;  //空表  NULL
	if(NULL == pLink)
	{
		return LINK_ERR;
	}
    //创建新结点
	pNode = create_node(tData);

	//当表为空时,pNode就是第一个结点
	if(NULL == pTmp)
	{
		pLink->pHead = pNode;
		pLink->count++;
		return LINK_OK;
	}
	//找到链表的最后一个结点
	while(pTmp->pNext != NULL)
	{
		pTmp = pTmp->pNext;
	}
	//将新的结点插入
	pTmp->pNext = pNode;
	pLink->count++;
	return LINK_OK;
}

//按位置插入
//参数1:单链表
//参数2:要插入的位置
//参数3:存放数据元素的结构体
int insert_item_link(Link *pLink,int pos,data_t tData)
{
	LinkNode *pNode = NULL;
	LinkNode *pTmp = pLink->pHead;
	int i;
	if(NULL == pLink || pos < 0 || pos > pLink->count)
	{
		return LINK_ERR;
	}
	//创建新结点
	pNode = create_node(tData);
	//找到要插入位置的前一个结点
	for(i = 0; i < pos-1; i++)
	{
		pTmp = pTmp->pNext;
	}

	//插入
	//如果是空表,pTmp = NULL
	if(0 == pLink->count)
	{
		pLink->pHead = pNode;
	}
	else
	{
		pNode->pNext = pTmp->pNext;
		pTmp->pNext = pNode;
	}

	pLink->count++;
	return LINK_OK;
}

//头部删除
//参数1:单链表
//参数2:存放被删除数据元素的结构体
int pop_head_link(Link *pLink,data_t *pData)
{
	LinkNode *pDel = pLink->pHead;
	//入参检查
	if(NULL == pLink)
	{
		return LINK_ERR;
	}
	//空表
	if(0 == pLink->count)
	{
		return LINK_EMPTY;
	}
	//删除	
	pLink->pHead = pDel->pNext;
	*pData = pDel->data;
	free(pDel);
	pDel = NULL;
	//元素个数-1
	pLink->count--;
	return LINK_OK;

}

//尾部删除
//参数1:单链表
//参数2:存放被删除数据元素的结构体
int pop_back_link(Link *pLink,data_t *pData)
{
	LinkNode *pTmp = pLink->pHead;
	LinkNode *pDel = NULL;
	if(NULL == pLink )
	{
		return LINK_ERR;
	}
	if(0 == pLink->count)
	{
		return LINK_EMPTY;
	}
	while(pTmp->pNext->pNext != NULL)
	{
		pTmp = pTmp->pNext;
	}
	pDel = pTmp->pNext;
	*pData = pDel->data;
	free(pDel);
	pDel = NULL;
	pTmp->pNext = NULL;
	pLink->count--;
	return LINK_OK;
}

//按位置删除
//参数1:单链表
//参数2:要删除的位置
//参数3:存放被删除数据元素的结构体
int delete_item_link(Link *pLink,int pos,data_t *pData)
{
	LinkNode *pDel = NULL;
	LinkNode *pTmp = pLink->pHead;
	int i;
	if(NULL == pLink || pos < 0 || pos >= pLink->count)
	{
		return LINK_ERR;
	}
	 //如果是空表
	if(0 == pLink->count)
	{
		return LINK_EMPTY;
	}

	pDel = pTmp;
    //找到要删除结点的前一个结点
	for(i = 0; i < pos-1; i++)
	{
	 	pTmp = pTmp->pNext;
	}
	//删除结点
	//如果只有一个结点或者要删除的是头结点
	*pData = pDel->data;
	if(0 == pos)
	{
		pLink->pHead = pDel->pNext;  //NULL
	}
	else
	{
		pDel = pTmp->pNext;
		pTmp->pNext = pDel->pNext;
	}
	free(pDel);
	pDel = NULL;
	pLink->count--;
   	return LINK_OK;
}

//查找(按名字查找,查找到所有信息)
//参数1:单链表
//参数2:要查找的名字
//参数3:存放被查找信息的结构体
int find_item_link(Link *pLink,data_t tData,data_t *pData)
{
	LinkNode *pTmp = pLink->pHead;
	if(NULL == pLink)
	{
		return LINK_ERR;
	}
	if(0 == pLink->count)
	{
		return LINK_EMPTY;
	}
	while(0 != strcmp(tData.name,pTmp->data.name))
	{
		pTmp = pTmp->pNext;
		if(NULL == pTmp)
		{
			break;
		}
	}
	if(pTmp != NULL)
	{
		//strcpy(pData->name,pTmp->data.name);
		//pData->age = pTmp->data.age;
		*pData = pTmp->data;
	}
	else
	{
		return LINK_ERR;
	}

	return LINK_OK;

}

//更新
//参数1:单链表
//参数2:更新的位置
//参数3:要更新的内容
int update_item_link(Link *pLink,int pos,data_t tData)
{
	int i;
	LinkNode *pTmp = pLink->pHead;
	if(NULL == pLink || pos < 0 || pos > pLink->count)
	{
		return LINK_ERR;
	}
	if(0 == pLink->count)
	{
		return LINK_EMPTY;
	}
	for(i = 0;i < pos;i++)
	{
		pTmp = pTmp->pNext;
	}
	pTmp->data = tData;
	return LINK_OK;

}

//显示
//参数:单链表
void show_link(Link *pLink)
{
	LinkNode *pTmp = pLink->pHead;
	if(NULL == pLink)
	{
		return;
	}
	while(pTmp != NULL)
	{
		printf("name:%s, age:%d\n",pTmp->data.name,pTmp->data.age);
		pTmp = pTmp->pNext;
	}
}


link.h

#ifndef _LINK_H_
#define _LINK_H_

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

//定义一个枚举设置错误信息返回值
enum LINK_OP
{
	LINK_ERR = -1,
	LINK_OK,
	LINK_EMPTY
};

//描述数据元素的结构体
typedef struct student
{
	char name[20];				//学生姓名
	int age;					//学生年龄
}data_t;

//描述单链表节点的结构体
typedef struct LinkNode
{
	data_t data;       			//数据元素
	struct LinkNode *pNext; 	//下一个节点的首地址
}LinkNode;

//描述单链表的结构体
typedef struct Link
{
	LinkNode *pHead;			//第一个结点的首地址
	int count;					//一共有多少个结点
}Link;


//创建一个空的单链表
//返回值单链表的首地址
Link *create_link();

//销毁一个单链表
//参数:单链表的地址
void destroy_link(Link **ppLink);

//头部插入
//参数1:单链表
//参数2:存放数据元素的结构体
int push_head_link(Link *pLink,data_t tData);

//尾部插入
//参数1:单链表
//参数2:存放数据元素的结构体
int push_back_link(Link *pLink,data_t tData);

//按位置插入
//参数1:单链表
//参数2:要插入的位置
//参数3:存放数据元素的结构体
int insert_item_link(Link *pLink,int pos,data_t tData);

//头部删除
//参数1:单链表
//参数2:存放被删除数据元素的结构体
int pop_head_link(Link *pLink,data_t *pData);

//尾部删除
//参数1:单链表
//参数2:存放被删除数据元素的结构体
int pop_back_link(Link *pLink,data_t *pData);

//按位置删除
//参数1:单链表
//参数2:要删除的位置
//参数3:存放被删除数据元素的结构体
int delete_item_link(Link *pLink,int pos,data_t *pData);

//查找(按名字查找,查找到所有信息)
//参数1:单链表
//参数2:存放数据元素的结构体
//参数3:要查找的名字
int find_item_link(Link *pLink,data_t tData,data_t *pData);

//更新
//参数1:单链表
//参数2:要更新的内容
int update_item_link(Link *pLink,int pos,data_t tData);

//显示
//参数1:单链表
void show_link(Link *pLink);

//菜单
//参数:单链表
void menu(Link *pLink);

void fileopen(Link *pLink);
void fileclose(Link *pLink);

#endif

2.3栈 

栈是一种先进后出的数据结构,它只允许在一端进行插入和删除操作,称为栈顶(只允许在栈顶操作)。

特点:
1.只允许在一端进行操作(栈顶)

2.插入和删除都在一端进行(一般比如链式存储就在头部进行,头部插入和头部删除)

3.先进后出

应用场景:括号匹配等

括号匹配相关代码

main.c

#include <stdio.h>
#include "stack.h"

//程序一运行起来就可以入栈
//知道输入‘#’就全部出栈

int main()
{
	data_t tData;
	data_t buf[100] = {0};
	int i = 0;
	int count = 0;
	int ret = 0;
	Stack *pStack = create_stack();
	if(NULL == pStack)
	{
		printf("create stack error\n");
		return -1;
	}

/*
	//入栈
	while(1)
	{
		tData = getchar();
		if(tData == '#')
		{
			break;
		}
		push_stack(pStack,tData);
	}

	//出栈
	while(STACK_EMPTY != pop_stack(pStack,&tData))
	{
		printf("%c ",tData);
	}
	putchar(10);
*/
	
	printf("输入一串带括号的字符:\n");
	fgets(buf,100,stdin);

	for(i = 0;i < strlen(buf);i++)
	{
		if('(' == buf[i])
		{
			push_stack(pStack,buf[i]);
		}
		else if(')' == buf[i])
		{
			ret = pop_stack(pStack,&tData);
			if(STACK_EMPTY != ret)
			{
				count++;
			}
		}
	}

	printf("一共有%d对()\n",count);
	destroy_stack(&pStack);
	return 0;
}

 stack.c

#include "stack.h"

static StackNode *create_node(data_t tData)
{
	StackNode *pNode = (StackNode*)malloc(sizeof(StackNode));
	if(NULL ==pNode)
	{
		return NULL;
	}
	memset(pNode,0,sizeof(StackNode));
	pNode->data = tData;

	return pNode;
}

//创建栈
Stack *create_stack()
{
	Stack *pStack = (Stack*)malloc(sizeof(Stack));
	if(NULL == pStack)
	{
		return NULL;
	}
	memset(pStack,0,sizeof(Stack));

	return pStack;
}
//销毁栈
void destroy_stack(Stack **ppStack)
{
	if(NULL == ppStack || NULL == *ppStack)
	{
		return;
	}
	if((*ppStack)->count > 0)
	{
		while((*ppStack)->pTop != NULL)
		{
			pop_stack(*ppStack,NULL);
		}
	}
	free(*ppStack);
	*ppStack = NULL;


}
//进栈(压栈)
int push_stack(Stack *pStack,data_t tData)
{
	//入参检查
	if(NULL == pStack)
	{
		return STACK_ERR;
	}
	StackNode *pNode = create_node(tData);
	if(0 == pStack->count)
	{
		pStack->pTop = pNode;
	}
	else
	{
		pNode->pNext = pStack->pTop;
		pStack->pTop = pNode;
	}
	pStack->count++;
	return STACK_OK;
}

//出栈
int  pop_stack(Stack *pStack,data_t *pData)
{
	StackNode *pDel = pStack->pTop;
	if(NULL == pStack)
	{
		return STACK_ERR;
	}
	if(0 == pStack->count)
	{
		return STACK_EMPTY;
	}
	if(pData != NULL)
	{
		*pData = pDel->data;
	}
	pStack->pTop = pDel->pNext;
	free(pDel);
	pDel = NULL;
	pStack->count--;
	return STACK_OK;
}

stack.h

#ifndef _STACK_H_
#define _STACK_H_

#include <stdlib.h>
#include <string.h>

enum STACK_OP
{
	STACK_ERR = -1,
	STACK_OK,
	STACK_EMPTY
};
typedef char data_t;

//描述结点的结构体
typedef struct StackNode 
{
	data_t data;
	struct StackNode *pNext;
} StackNode;

//描述栈的结构体
typedef struct Stack
{
	StackNode *pTop;
	int count;
}Stack;

//创建栈
Stack *create_stack();

//销毁栈
void destroy_stack(Stack **ppStack);

//进栈(压栈)
int push_stack(Stack *pStack,data_t tData);

//出栈
int pop_stack(Stack *pStack,data_t *pData);


#endif

2.4队列 

队列是一种先进先出的数据结构,它只允许在一端进行插入操作,称为队尾,在另一端进行删除操作,称为队头。
特点:

1.能够保证数据的顺序性,符合排队的规则。

应用场景:消息队列(叫号)等

顺序队列相关代码

queue.c

#include "queue.h"
//创建
Queue *create_queue()
{
	Queue *pQueue = (Queue*)malloc(sizeof(Queue));
	if(NULL == pQueue)
	{
		return NULL;
	}
	memset(pQueue,0,sizeof(Queue));
	return pQueue;
}

//销毁
void destroy_queue(Queue **ppQueue)
{
	if(NULL == ppQueue || NULL == *ppQueue)
	{
		return;
	}
	free(*ppQueue);
	*ppQueue = NULL;
}
//入队
int enter_queue(Queue *pQueue,data_t tData)
{
	if(NULL == pQueue)
	{
		return QUEUE_ERR;
	}
	//队满
	if(SIZE == pQueue->count)
	{
		return QUEUE_FULL;
	}
	pQueue->data[pQueue->iTail] = tData;
	if(pQueue->iTail < SIZE-1)
	{
		pQueue->iTail++;
	}
	else
	{
		pQueue->iTail = 0;
	}
	pQueue->count++;
	return QUEUE_OK;
}
//出队
int leave_queue(Queue *pQueue,data_t *pData)
{
	if(NULL == pQueue || NULL == pData)
	{
		return QUEUE_ERR;
	}
	if(0 == pQueue->count)
	{
		return QUEUE_EMPTY;
	}
	if(0 == pQueue->count)
	{
		return QUEUE_EMPTY;
	}
	*pData = pQueue->data[pQueue->iHead];
	if(pQueue->iHead < SIZE-1)
	{
		pQueue->iHead++;
	}
	else
	{
		pQueue->iHead = 0;
	}
	pQueue->count--;
	return QUEUE_OK;
}

queue.h

#ifndef _QUEUE_H_
#define _QUEUE_H_

#include <stdlib.h>
#include <string.h>

#define SIZE 5

enum QUEUE_OP
{
	QUEUE_ERR = -1,
	QUEUE_OK,
	QUEUE_EMPTY,
	QUEUE_FULL
};

typedef char data_t;

typedef struct Queue
{
	data_t data[SIZE];
	int iHead;//队头元素下标
	int iTail;//队尾元素下标
	int count;
}Queue;

//创建
Queue *create_queue();
//销毁
void destroy_queue(Queue **ppQueue);
//入队
int enter_queue(Queue *pQueue,data_t tData);
//出队
int leave_queue(Queue *pQueue,data_t *pData);
#endif

main.c

#include <stdio.h>
#include "queue.h"


//程序一运行起来就可以入队
//直到输入'#'就全部出队

int main()
{
	data_t tData;
	Queue *pQueue = create_queue();
	if(NULL == pQueue)
	{
		printf("create_queue error!\n");
		return -1;
	}

	//入队
	while(1)
	{
		tData = getchar();
		if(tData == '#')
		{
			break;
		}
		enter_queue(pQueue, tData);
	}

    //出队
	while(QUEUE_EMPTY != leave_queue(pQueue, &tData))
	{
		printf("%c ", tData);
	}
	printf("\n");
	printf("%d\n",pQueue->iHead);
	printf("%d\n",pQueue->iTail);
	getchar();	
	//入队
	while(1)
	{
		tData = getchar();
		if(tData == '#')
		{
			break;
		}
		enter_queue(pQueue, tData);
	}
	
	//出队
	while(QUEUE_EMPTY != leave_queue(pQueue, &tData))
	{
		printf("%c ", tData);
	}
	printf("\n");

	destroy_queue(&pQueue);
	return 0;
}

2.5树

树是一种分层的数据结构,它由一个根节点和若干个子节点组成,每个子节点又可以有自己的子节点,形成一个层次结构。

特点:

1.能够表示复杂的层次关系,提高数据的检索效率。

2.操作比较复杂,需要递归或者栈来实现遍历。

应用场景:文件系统、XML文档、二叉搜索树、红黑树等。

相关代码

tree.h

#ifndef _TREE_H_
#define _TREE_H_

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

typedef char data_t;

//描述节点的结构体
typedef struct TreeNode
{
	data_t data;
	struct TreeNode *lChild; //左子树的根结点
	struct TreeNode *rChild; //右子树的根结点
} TreeNode;


//创建树
//返回值为根结点地址
TreeNode *create_tree(); 
//先序遍历
void pre_order(TreeNode *pRoot);
//中序遍历
void mid_order(TreeNode *pRoot);
//后序遍历
void post_order(TreeNode *pRoot);
//销毁树
void destroy_tree(TreeNode **ppRoot);
#endif

tree.c

#include "tree.h"


TreeNode *create_node(data_t tData)
{
	TreeNode *pNode = (TreeNode *)malloc(sizeof(TreeNode));
	if(NULL == pNode)
	{
		return NULL;
	}
	//lChild = NULL  rChild=NULL
	memset(pNode, 0, sizeof(TreeNode));
	pNode->data = tData;
    return pNode;
}

//创建树
//返回值为根结点地址
TreeNode *create_tree()
{
	TreeNode *pNode = NULL;
	//输入左右节点的元素的值,如果没有左右子树输入#
    data_t c;
	c = getchar();
	if('#' == c)
	{
		return NULL;  //这棵树创建结束
	}
	//创建结点  根结点
	pNode = create_node(c);
    //创建这个根结点的左子树
	pNode->lChild = create_tree();
    //创建这个根结点的右子树
	pNode->rChild = create_tree();
	return pNode;
}
//先序遍历
void pre_order(TreeNode *pRoot)
{
	if(NULL == pRoot)
	{
		return;
	}
	printf("%c ", pRoot->data);
	pre_order(pRoot->lChild);
	pre_order(pRoot->rChild);
}
//中序遍历
void mid_order(TreeNode *pRoot)
{
	if(NULL == pRoot)
	{
		return;
	}
	mid_order(pRoot->lChild);
	printf("%c ", pRoot->data);
	mid_order(pRoot->rChild);
}
//后序遍历
void post_order(TreeNode *pRoot)
{
	if(NULL == pRoot)
	{
		return;
	}
	post_order(pRoot->lChild);
	post_order(pRoot->rChild);
	printf("%c ", pRoot->data);
}
//销毁树
void destroy_tree(TreeNode *pRoot)
{
	if(NULL== pRoot)
	{
		return;
	}
	//free左子树
	destroy_tree(pRoot->lChild);
	//free右子树 
	destroy_tree(pRoot->rChild);
	//free根结点 
	free(pRoot);
	pRoot = NULL;
}

main.c

#include "tree.h"


int main()
{
	TreeNode *pRoot = create_tree();
	pre_order(pRoot);
	printf("\n");
	mid_order(pRoot);
	printf("\n");
	post_order(pRoot);
	printf("\n");
	destroy_tree(pRoot);
	pRoot = NULL;
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值