#include <stdio.h> //所需的头文件
#include <stdlib.h>
#include <time.h>
struct node //结点包含值域和指针域俩部分
{
int num;
struct node * next;
};
typedef struct node Node; //对想要多次重复使用的较长的代码进行重新定义
typedef struct node * Link;
void create_link(Link * head) //表头为空,即不带表头结点 的单链表
{
*head = NULL;
}
void insert_node_head(Link * head,Link new_node) //头部插入,参数包括头部和插入的结点
{
new_node->next = *head; //插入头部只有一种情况
*head = new_node;
}
void is_malloc_ok(Link new_node) //动态分配空间是否成功
{
if(new_node == NULL)
{
printf("malloc error!\n");
exit(-1);
}
}
void create_new_node(Link * new_node) //创建结点,需要分配空间和判断是否分配成功
{
*new_node = (Link)malloc(sizeof(Node));
is_malloc_ok(*new_node);
}
void insert_node_tail(Link * head,Link new_node) //尾部插入,参数与头部插入一致
{
Link p;
p = *head; //定义一个指针为头指针
if(*head == NULL) //分俩种情况,链表为空和不为空,为空的方法与头部插入一样
{
*head = new_node;
new_node->next = NULL;
}
else
{
while(p->next != NULL) //指针寻找到最后一个结点,将其插入在尾部
{
p = p->next;
}
p->next = new_node;
new_node->next = NULL;
}
}
void release_link(Link * head) //链表空间的释放
{
Link p;
p = *head;
while(*head != NULL) //让头指针指向第二个结点,然后释放第一个结点
{
*head = (*head)->next; //循环到最后一个
free(p);
p = *head;
}
}
void display_link(Link head) //链表的显示
{
Link p;
p = head;
if(head == NULL)
{
printf("Link is empty!\n");
return;
}
while(p != NULL)
{
printf("num = %d\n",p->num);
p = p->next;
}
}
void insert_node_mid_head(Link * head,Link new_node,int loc) //中间插入( 头部插入)
{ //多了一个参数,即寻找相要插入在哪个数的哪个位置
Link p,q;
if(NULL == *head) //如果链表为空的一种情况
{
*head = new_node;
new_node->next = NULL;
}
else //定义俩个指针
{
q = *head;
p = (*head)->next;
if(q->num == loc) //第一个结点为想要插入的结点位置
{
new_node->next = *head;
*head = new_node;
}
else
{
while(p != NULL && p->num != loc) //寻找想要插入的位置,直到找到为止
{
q = p;
p = p->next;
}
if(p == NULL) //如果没有要找的数,者插入在链表的尾部
{
q->next = new_node;
new_node->next = NULL;
}
else //找到要插入的结点位置
{
q->next = new_node;
new_node->next = p;
}
}
}
}
void insert_node_mid_tail(Link * head,Link new_node,int loc) //中间插入(尾部插入),方法同上
{
Link q,p;
if(NULL == *head)
{
new_node->next = *head;
*head = new_node;
}
else
{
q = *head;
p = (*head)->next;
if(p->num == loc)
{
q->next = new_node;
new_node->next = p;
}
else
{
while(p != NULL && q->num != loc)
{
q = p;
p = p->next;
}
if(p == NULL)
{
q->next = new_node;
new_node->next = NULL;
}
else
{
q->next = new_node;
new_node->next = p;
}
}
}
}
void delete_node(Link * head,int num) //删除结点
{
Link q,p;
if(*head == NULL)
{
printf("Link is empty! no such node!\n");
return;
}
if((*head)->num == num) //第一个结点为想要删除的结点情况
{
p = *head;
*head = (*head)->next;
free(p);
}
else //找到想要删除的结点,利用定义的俩个指针,q在前p在后
{
q = *head;
p = (*head)->next;
while(p != NULL && p->num != num)
{
q = p;
p = p->next;
}
if(p == NULL)
{
printf("no such node!\n");
}
else
{
q->next = p->next; //找到要删除的结点,让q指向p的下一个结点,释放p结点
free(p);
}
}
}
void insert_node_sort_asc(Link *head,Link new_node) //顺序插入,这里演示从小到到的排序
{
Link q,p;
if(*head == NULL)
{
*head = new_node;
new_node->next = NULL;
}
else // 想要的插入的结点比头结点小,则插入在头部
{
q = *head;
p = (*head)->next;
if((*head)->num > new_node->num)
{
new_node->next = *head;
*head = new_node;
}
else //寻找到比插入结点大的结点,插入在这个数前面
{ //同样的
while(p != NULL && p->num < new_node->num)
{
q = p;
p = p->next;
}
q->next = new_node;
new_node->next = p;
}
}
}
void reverse_link(Link *head) //倒序输出,需要定义三个指针
{
Link p1,p2,p3;
if(*head == NULL)
{
printf("Link is empty!\n");
return;
}
if((*head)->next == NULL)
{
return;
}
p1 = *head;
p2 = (*head)->next;
p3 = p2->next;
while(p3 != NULL)
{
p2->next = p1;
p1 = p2;
p2 = p3;
p3 = p3->next;
}
p2->next = p1;
(*head)->next = NULL;
*head =p2;
return;
}
int main()
{
int num;
int loc;
int i;
Link head = NULL;
Link new_node = NULL;
srand((unsigned)time(NULL)); //生成任意数
create_link(&head); //创建链表
for(i = 0;i < 10;i++)
{
create_new_node(&new_node); //创建结点
new_node->num = rand() % 100; //结点的值域为任意数
// insert_node_head(&head,new_node); //头部插入
// insert_node_tail(&head,new_node); //尾部插入
insert_node_sort_asc(&head,new_node); //排序插入,从小到大或从大到小的顺序
}
display_link(head); //显示链表内容
/* printf(":\n");
scanf("%d",&loc);
printf("\n");
create_new_node(&new_node); //创建一个结点,插入已有的链表,值域为100
new_node->num = 100;
insert_node_mid_head(&head,new_node,loc); //插入在这个数的头部
//insert_node_mid_tail(&head,new_node,loc); //插入在这个数的尾部,这俩种插入也叫中间插入
display_link(head);*/
/* printf("please input num to delete!\n"); //输入一个想要删除的结点的数
scanf("%d",&num);
delete_node(&head,num); //删除结点
display_link(head);*/
// display_link(head);
printf("\n");
reverse_link(&head); //倒序输出单链表
display_link(head);
release_link(&head); //链表空间的释放
display_link(head);
return 0;
}