目录
1.什么是数据结构
数据结构:数据(由数据元素组成(一种基本数据类型或者结构体))+结构(逻辑结构+存储结构)+操作(增删改查)
1.2结构
结构分为逻辑结构和存储结构
1.2.1逻辑结构:
数据元素和数据元素之间的逻辑关系--如线性结构、非线性(树状、图状)结构
1.2.2存储结构:
数据在内存中的存储方式
很多结构变量存放在内存里----如顺序存储(一次性开辟一块很大的空间--数组)、链式存储(内存空间是不连续的,上一个元素可以通过地址找到下一个元素
逻辑结构是线性,存储结构是顺序-----顺序表(数组)
逻辑结构是线性,存储结构是链式-----链表
逻辑结构是树状,存储结构是顺序----树
逻辑结构是树状,存储结构是链式---树
1.3操作
创建、插入、删除、查找、修改、销毁---内存里(不能永久保存)
- 操作完之后将内存中的数据保存到文件
启动系统之后将保存在文件中的数据读到内存
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;
}