链表
- 单链表
//一个结点
typedef struct node{
void*data;
struct node*next;
} Node;
//链表,持有头节点、尾结点及当前结点
typedef struct link_list{
Node* head;
Node* tail;
Node* current;
}LinkedList;
在使用链表之前要先初始化:
void init_list(LinkedList *list)
{
list->head=NULL;
list->tail=NULL;
list->current=NULL;
}
在表头添加结点:
void addHead(LinkedList *list,void*data)
{
Node* node=(Node*)malloc(sizeof(Node));
node->data=data; //先创建结点
if(list->head=NULL)
{
list->tail=node;
node->next=NULL;
}
else
{
node->next=list->head; //把原本的头结点连接到新结点的后面
}
list->head=node; //更新头结点的值
}
在表尾添加结点:
void addTail(LinkedList *list,void*data)
{
Node* node=(Node*)malloc(sizeof(Node));
node->data=data;
node->next=NULL;//先创建结点
if(list->head=NULL)
{
list->head=node;
}
else
{
list->tail->next=node;
}
list->tail=node; //更新头结点的值
}
返回带有指定数据的结点:
void delete(LinkedList *list,Node *node)
{
if(node==list->head) //删除的是表头。
{
if(list->head->next==NULL)
{
list->head=list->tail=NULL;
}else
{
list->head=list->head->next;
}
}
else
{
Node*tmp=list->head;
while(tmp!=NULL&&tmp->next!=node)
{
tmp=tmp->next;
}
if(tmp!=NULL)
{
tmp->next=node->next;
}
}
free(node); //释放结点
}
队列
队列是一种线性数据结构,讲究先进先出,入队操作就是将节点添加到链表头、出列就是从链表尾删除节点。
链表的初始化和之前的一样,节点添加到链表头同上
下面的操作是从链表尾删除节点:
//分为3种情况,空队列,单字节队列,多字节队列
typedef LinkedList Queue ;
void queuedele(Queue * queue)
{
Node *tmp=queue->head;
void *data;
if(queue->head==NULL)
{
data=NULL;
}
elseif(queue->head==queue->tail)
{
queue->head=queue->tail=NULL;
data=tmp->data;
free(tmp);
}
else
{
while(tmp->next!=queue->tail)
{
tmp=tmp->next;
}
queue->tail=tmp;
tmp=tmp->next;
queue->tail->next=NULL;
data=tmp->data;
free(tmp);
}
return data;
}
栈
栈数据结构也是一种链表,行为是先进后出,我们用addHead函数实现入栈,出栈需要增加一个新函数来删除头节点。
typedef LinkedList Stack;
void *pop(Stack * stack)
{
Node *node=stack->head;
if(node==NULL)
{
return NULL;
}
elseif(node==stack->tail)
{
stack->head=stack->tail=NULL;
void *data=node->data;
free(node);
return data;
}
else
{
stack->head= stack->head->next;
void *data=node->data;
free(node);
return data;
}
}
树
树可以有任意数量的子节点,不过,二叉树比较常见,它的每个节点能有0个、1个或是2个子节点。子节点要么是左子节点,要么是右子节点。没有子节点的节点称为叶子节点,就跟树叶一样。
typedef struct tree
{
struct tree * left;
struct tree * right;
void * data;
}TreeNode;
二叉查找树:
插入的新节点后,这个节点的所有左子节点的值都比父节点小,所有右节点的值都比父节点的值大。(左小,右大)
//因为存在改变节点指针所以要传递双重指针
void insertNode(TreeNode **root,COMPARE compare,void *data)
{
//定义申请节点的空间,并且初始化。
TreeNode *node=(TreeNode *)malloc(sizeof(TreeNode));
node->data=data;
node->left=NULL;
node->right=NULL;
//判断根节点是否为空,如果为空,就把新节点赋值给根节点
if(*root==NULL)
{
*root==node;
return;
}
while(1)
{
if(compare((*root)->data,data)>0)
{
if((*root)->left!=NULL)
{
*root=(*root)->left;
}
else
{
(*root)->left=node;
break;
}
}
else
{
if((*root)->right!=NULL)
{
*root=(*root)->right;
}
else
{
(*root)->right=node;
break;
}
}
}
TreeNode *tree=NULL;
insertNode(&tree,(COMPARE) compare,samuel);
insertNode(&tree,(COMPARE) compare,sally);
insertNode(&tree,(COMPARE) compare,susan);
遍历二叉树
遍历二叉树有三种:前序、中序、后序,它们步骤相同。
- 访问节点
处理节点 - 往左
转移到左子节点 - 往右
转移到右子节点
void inOrder(TreeNode*root,DISPLAY display)
{
if(root!=NULL)
{
inOrder(root->left,display);
display(root->data);
inOrder(root->right,display);
}
void postOrder(TreeNode*root,DISPLAY display)
{
if(root!=NULL)
{
postOrder(root->left,display);
postOrder(root->right,display);
display(root->data);
}
void preOrder(TreeNode*root,DISPLAY display)
{
if(root!=NULL)
{
display(root->data);
preOrder(root->left,display);
preOrder(root->right,display);
}