您的位置:首页 > 编程语言

带表头节点的单向循环链表编程

2016-11-08 09:43 429 查看
 对于单链表,由于每个结点只存储了向后的指针,到了尾标志就停止了向后的操作,这样,当某一个结点找不到前驱结点了,也不能回去找。而我们现在要解决这个问题,就要利用循环链表。

 将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。

 循环链表解决了一个很麻烦的问题:如何从一个结点出发,访问到链表的全部结点。

 为了使空链表与非空链表处理一致,我们通常设一个头结点,当然,并不是说循环链表一定要有头结点。

 其实循环链表和单链表的主要差异在于循环的判断条件上,之前是判断temp->next是否为空,现在是temp->next不等于头结点

知识点:

1.循环链表是单链表的变形。

2.循环链表最后一个结点的 link 指针不 为NULL,而是指向了表的前端。

3.为简化操作,在循环链表中往往加入表头结点。

4.循环链表的特点是:只要知道表中某一结点的地址,就可搜寻到所有其他结点的地址。



/*****************************************************
copyright (C), 2014-2015, Lighting Studio. Co.,     Ltd.
File name:
Author:Jerey_Jobs    Version:0.1    Date:
Description:
Funcion List:
*****************************************************/

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

struct node
{
int num;
struct node * next;
};

typedef struct node Node;
typedef struct node * Link;

void creat_link(Link * head)
{
(*head) = (Link)malloc(sizeof(Node)) ;  //创建一个新的节点,返回其地址
if(NULL == (*head))
{
printf("malloc error!\n");
exit(-1);
}

(*head) -> next = *head;

}
/*
=========================
功能:从链表头部插入结点
返回:void
=========================
*/
void insert_node_head(Link * head,Link new_node)
{
Link tmp = *head;

new_node->next = tmp->next;
tmp -> next = new_node;
}
/*
=========================
功能:从链表尾部插入结点
返回:void
=========================
*/
void insert_node_tail(Link *head,Link newnode)
{
Link temp = *head;

while (temp->next != *head)  //找到最后一个结点
{
temp = temp->next;
}

temp->next = newnode;       //插入结点
newnode->next = *head;
}

void insert_node(Link * head,Link new_node,int n)
{
Link tmp = NULL;
Link q = NULL;
tmp = *head;

if(NULL == *head)     //链表为空时
{
new_node -> next = NULL;
*head = new_node;        //使头头指针指向最新的节点
}
else                  //链表不为空时
{
while((tmp->num) < n && (tmp->next != NULL))    // 寻找插入的位置
{
q = tmp;
tmp = tmp -> next;
}

if(((*head) -> next) == NULL)  //只有一个节点时
{
if(tmp->num < n)    // 这个节点 小于 新节点时
{
(*head)->next = new_node;
new_node->next = NULL;
}
else //这个节点 大于 新的节点时
{
new_node->next = *head;
*head = new_node;
}
}
else  //不止一个节点时
{
if(tmp == *head)  //头处
{
new_node->next = *head;
*head = new_node;
}
else //非头处
{
if(tmp->next != NULL)  //非尾处
{
q -> next = new_node;
new_node -> next = tmp;
}
else // 尾处
{
if(n > (tmp -> num)) // 新节点数据大于尾
{
tmp -> next = new_node;
new_node -> next = NULL;
}
else //新节点数据小于尾
{
q -> next = new_node;
new_node -> next = tmp;
}
}
}
}
}
}

/*
=========================
功能:从链表指点节点后插入节点
返回:void
=========================
*/
void insert_node_mid(Link * head,Link new_node,int num)    //插入节点
{
Link  tmp = (*head)->next;

if(*head == (*head)->next)
{
printf("link is empty !\n");
return;
}
else
{
while(tmp -> num != num && tmp -> next != (*head)) //找到要插入的位置
{
tmp = tmp -> next;
}

if(tmp -> num == num)  //
{
/*if((*head) -> next == tmp)
{
new_node -> next = tmp;
(*head) -> next = new_node;
}
else */
if( tmp -> next == (*head))  /其实这个里考虑多余
{
new_node -> next = (*head);
tmp -> next = new_node;
}
else
{
new_node -> next = tmp -> next;
tmp -> next = new_node;
}
}
else
{
printf("no such node!\n");
}
}
}
/*
=========================
功能:删除指定节点
返回:void
=========================
*/
void delete_node(Link * head,int num_delete)
{
Link tmp = (*head)->next;
Link p   = NULL;

if((*head) == tmp)
{
printf("link is empty !\n");
return;
}
else
{
while(tmp -> num != num_delete && tmp -> next != NULL)
{
p   = tmp;      //需要一个指针用于跟踪
tmp = tmp -> next;
}

if(tmp -> num == num_delete) //找到这个位置
{
if( tmp == (*head)->next)
{
(*head) -> next = tmp -> next;
free(tmp);
}
else if(tmp -> next == (*head))
{
p -> next = (*head);
free(tmp);
tmp = NULL;
}
else
{
p -> next =  tmp -> next;
free(tmp);
tmp = NULL;
}
}
else
{
printf("no such node!\n");
}
}
}
/*
=========================
功能:从链表反转
返回:void
=========================
*/
void revers_link(Link * head)
{
Link p1,p2,p3;
Link tmp  = (*head)->next;

if((*head) -> next == (*head)) return;

else if((*head) -> next -> next == (*head))
{
(*head) -> next = tmp -> next;
tmp -> next -> next= tmp;
tmp -> next = (*head);

return;
}

else
{
p3 = tmp;
p2 = p3 -> next;
p1 = p2 -> next;
while(p1 -> next != (*head))
{
p2 -> next = p3;
p3 = p2;
p2 = p1;
p1 = p1->next;
}
p2 -> next = p3;
p1 -> next = p2;
(*head) -> next -> next = (*head);
(*head) -> next = p1;
}
}

/*
=========================
功能:释放链表
返回:void
=========================
*/
void free_node(Link * head)
{
Link tmp = (*head)->next;
Link p   = *head;

if( tmp == (*head))
{
printf("link is emtpy\n");
return;
}

while(  (*head)->next != (*head))
{
tmp = (*head)->next;
(*head) ->next = tmp -> next;
free(tmp);
tmp = NULL;
}
tmp = (*head)->next;
free(tmp);
tmp = NULL;
printf("Link is freed\n");
}
/*
=========================
功能:打印
返回:void
a957

=========================
*/
void display(Link head)
{
Link tmp;
tmp = head -> next;

if(head == head -> next)
{
printf("Link is empty\n");
}

while(tmp != head)
{
printf("num = %d\n",tmp->num);
tmp = tmp -> next;
}
}

int main()
{
Link head = NULL;
Link new_node = NULL;
int i;
int num_insert,num_delete;

creat_link(&head);   //创建用于指向表头结点的Link型指针(头指针),此时指向NULL。

for(i = 0; i <10; i++)
{
new_node = (Link)malloc(sizeof(Node)) ;  //创建一个新的节点,返回其地址
if(NULL == new_node)
{
printf("malloc error!\n");
exit(-1);
}
new_node -> num = i;  //节点赋值

insert_node_head(&head,new_node);    //插入节点(尾插)
//  insert_node(&head,new_node,new_node->num);
//  insert_node_tail(&head,new_node);    //插入节点(尾插)
}

display(head);
printf("请输入要插入的序号:");
scanf("%d",&num_insert);

new_node = (Link)malloc(sizeof(Node)) ;  //创建一个新的节点,返回其地址

if(NULL == new_node)
{
printf("malloc error!\n");
exit(-1);
}

new_node -> num = 321;  //节点赋值

insert_node_mid(&head,new_node,num_insert);    //插入节点(中间)
display(head);

printf("请输入要删除的序号:");
scanf("%d",&num_delete);

delete_node(&head,num_delete);
display(head);
printf("------------\n");

revers_link(&head);
display(head);
printf("------------\n");

free_node(&head);
printf("------------\n");
display(head);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: