c的结构体很像面向对象的类,所以我常常是以结构体开始复习c的。
就以一个链表开始吧:
一个链表我们输入信息,可以增删改查吧。
结构体的数据结构:
struct node {
char name[20];
int data;
struct node *next;
};
struct Link {
int length;
node *head;
node *tail;
};
typedef Link Link;
输入:
/**
* 输入节点信息
*/
node* input_Node_Info()
{
node *n = (node * )malloc(sizeof(struct node));
printf("input node infomation: name\t data\n");
scanf("%s", &n->name);
scanf("%d", &(n->data));
n->next = NULL;
return n;
}
打印单个的节点信息:
void print_Node_Info(node * l)
{
printf("the node infomation :\n");
printf("name = %s\t data = %d\n",l->name,l->data);
}
还有初始化链表:
Link * init()
{
Link * L = (Link *)malloc(sizeof(Link));
L->tail = L->head = NULL;
L->length = 0;
return L;
}
在链表的最后添加一个节点:
void add_node_end(Link * link,node * n)
{
if(link->head == NULL)
{
link->tail =n;
link->head =n;
}
else
{
link->tail->next= n;
link->tail = n;
}
link->length++;
}
在链表头添加节点:
void add_node_head(Link * link,node * n)
{
if(link->head == NULL)
{
link->tail =n;
link->head =n;
}
else
{
n->next = link->head->next ;
link->head = n;
}
link->length++;
}
还有就是在某个节点上添加节点,如想在第四个上添加一个一个节点(链表最少也得有三个吧),这就需要我们得到第3个节点,然后在第三个节点后面添加节点信息
这就说我们还得得到第三个节点了。
下面我们再写一个函数来查找第几个节点的信息。
node * get_node_by_id(Link * L,int id)
{
if(id<=0 || id >L->length )
{
printf("the n 越界了×××××××××××××××××××\n");
return NULL;
}
else
{
node *temp = L->head;
for(int i= 1;i<id;i++)
{
temp = temp->next;
}
return temp;
}
}
这其实有个缺陷就是不能在链表的结尾来添加节点信息,我们可以另类处理它.
void add_node_by_id(Link * L,node *n,int i)
{
if(i<=0)
{
add_node_head(L,n);
}
else if(i>=L->length)
{
add_node_end(L,n);
}
else{
node * result = get_node_by_id(L,i-1);
if(n != NULL)
{
n->next = result->next;
result->next = n; L->length++;
}
}
}
简单地说明下了,就是当输入的位置数值越界时,我们会返回NULL,但是我们可以在通过越界的位置为它添加节点,当i小于等于0,就插在链表头,大于等于链表的长度就插在链表尾部,ok了
还有就是打印整个链表的信息:
void print_Link_Info(Link * l)
{
printf("\t *******************print_Link_Info\n");
printf("\t *******************the length of linker is %d\n",l->length);
node * tem = l->head;
while(tem != NULL)
{
print_Node_Info(tem);
tem = tem->next;
}
}
这就说所有增加节点的部分。
下面我们开始删除节点的部分吧:
删除可以分为几种:删除头节点,删除尾节点,删除第几个节点,也可以删除符合信息的节点(是删除第一个符合条件哦节点还是所有的)
那就开始吧:
删除头节点:
void delete_node_head(Link *L)
{
node *head = L->head;
if(head != NULL)
{
L->head = head->next;
free(head);
L->length--;
}
}
删除某一个位置的节点,并将节点的信息给保存起来.
void node_to_node(node * des,node *src)
{
des->data = src->data;
strcpy(des->name,src->name);
}
void delete_node_by_pos(Link *L,int pos,node * pNode)
{
if(pos > L->length || pos < 0)
return ;
else if(pos == 1)
{
delete_node_head(L);
pNode = L->head;
}
else
{
node * n = get_node_by_id(L,pos-1);
node *temp = n->next;
n->next = temp->next;
node_to_node(pNode,temp);
free(temp);
L->length--;
}
}
还可以根据节点的信息来删除节点信息的,我们来看下:
/************************************************************************/
/* 删除Link中的含有data的第一个节点,将节点的信息返回到pNode中 */
/************************************************************************/
void delete_node_by_data(Link *L,int data,node *pNode)
{
if(L->head->data == data)
{
node_to_node(pNode,L->head);
free(L->head);
L->head = NULL;
L->length--;
return;
}
node * pre = L->head;
node *temp = L->head->next;
while(pre != NULL || temp != NULL )
{
if(temp->data == data)
{
node_to_node(pNode,temp);
pre->next = temp->next;
free(temp);
L->length--;
return;
}
else
{
pre =pre->next;
temp = temp->next;
}
}
}