一、代码:
#include <stdio.h>
#include <stdlib.h>
#define _ULL unsigned long long
/*definition of single link:each node can only visit it's next node, and visit it's pre node,the last link point to NULL*/
/*use scene:sort number. get the minnest number from R[0]~R[n-1] and swap with R[0]; compare with other sort method*/
//Link is a struct which has a ull type and a Link * pointer type; mylink is a new name of struct Link by use of typedef
typedef struct Link
{
_ULL value;
struct Link *next;
}mylink;
/*
quantity: init a mylink which has quantity number; add by tail;
https://blog.youkuaiyun.com/qq_52607834/article/details/115922172
*/
mylink* init_mylink(_ULL quantity)
{
printf("begin to init...\n");
_ULL i = 0;
mylink* head_node = (mylink*)malloc(sizeof(mylink)); //init a head node
head_node->value=0;
printf("in init_mylink, i:%d\n", i);
mylink* p_cursor_node = head_node; //a cursor pointer point to head_node
for(i = 1; i < quantity; i ++)
{
/*
create a new pointer and point it to an assigned value
each tmp_mylink has two addresses: an address of itself + an address point to other link node
*/
mylink* tmp_mylink = (mylink*)malloc(sizeof(mylink)); //malloc a new pointer
tmp_mylink->value = i; //value assignment
tmp_mylink->next = NULL; //pointer assignment
printf("in init_mylink, i:%d\n", i);
//point old pointer to new pointer, add by tail
p_cursor_node->next = tmp_mylink;
p_cursor_node=tmp_mylink; //p_cursor_node point to new added node
tmp_mylink->next = NULL;
}
return head_node;
}
void free_mylink(mylink* head_node)
{
printf("begin to free...\n");
int i = 0;
mylink* p_cursor_node = head_node;
//mylink* new_head_node = NULL;
while(NULL != p_cursor_node)
{
head_node = head_node->next;
free(p_cursor_node);
printf("free %dth inode success!\n", i++);
p_cursor_node = head_node;
}
}
void print_mylink(mylink* head_node)
{
int i = 0;
mylink* p_cursor_node = head_node;
while(NULL != p_cursor_node)
{
printf("the %dth inode's value:%llu\n", i++, p_cursor_node->value);
p_cursor_node = p_cursor_node->next;
}
}
/*add a value,after add,all value are also sorted*/
void add_mylink_sort(mylink* head_node, _ULL value)
{
int i = 0;
_ULL pre_pos = 0, next_value = -1;
mylink* p_cursor_node = head_node;
while(NULL != p_cursor_node)
{
//printf("the %dth inode's value:%llu, pre node's value:%llu\n", i, p_cursor_node->value, next_value);
pre_pos = i;
if(NULL != p_cursor_node->next)
next_value = (p_cursor_node->next)->value;
if(value >= p_cursor_node->value && value <= next_value)
{
mylink* add_node = (mylink*)malloc(sizeof(mylink)); //init a to-be-added node
add_node->value = value;
add_node->next = p_cursor_node->next;
p_cursor_node->next = add_node;
return;
}
p_cursor_node = p_cursor_node->next;
}
}
void del_mylink_sort(mylink** head_node, _ULL value)
{
int i = 0;
mylink* p_cursor_node = *head_node;
mylink* tmp_pre_node = NULL;
while(NULL != p_cursor_node)
{
//printf("the %dth inode's value:%llu\n", i++, p_cursor_node->value);
if(value == p_cursor_node->value)
{
if(NULL == tmp_pre_node)
{
printf("del %dth node in the head\n", i);
*head_node = p_cursor_node->next;
tmp_pre_node = *head_node;
p_cursor_node->next = *head_node;
}
else
{
printf("del %dth node in the middle.\n", i);
tmp_pre_node->next = p_cursor_node->next;
p_cursor_node->next = tmp_pre_node->next;
}
//no need traverse to the last node in a sorted link
if(value < (p_cursor_node->next)->value)
return;
}
else
{
tmp_pre_node = p_cursor_node;
}
p_cursor_node = p_cursor_node->next;
i ++;
}
}
void main(int argc, char *argv[])
{
if(argc < 2)
{
printf("should follow by one para\n");
exit(0);
}
mylink *mylink1 = NULL; // compile passed
/*Link *mylink2 = NULL;*/ // compile not passed, unknow type of 'Link', unless use struct Link
//step 1: init a single node link
mylink1 = init_mylink(atoi(argv[1]));
if(NULL == mylink1)
{
printf("init_mylink failed\n");
return;
}
//step 2:print all node link
print_mylink(mylink1);
//step 3:add a new node in middle of link, all value should Sort from small to large after insert
printf("add 3...\n");
add_mylink_sort(mylink1, 3);
print_mylink(mylink1);
//step 4:delete a node in middle of link, all value should Sort from small to large after delete
printf("del 3...\n");
del_mylink_sort(&mylink1, 3);
print_mylink(mylink1);
printf("del 0...\n");
del_mylink_sort(&mylink1, 0);
print_mylink(mylink1);
//step 5:free node link
free_mylink(mylink1);
}
二、运行环境:linux 64
三、编译方法:gcc single_link_list.c -g
四、运行及结果:
[root@localhost single_link_list]# ./a.out 5
begin to init...
in init_mylink, i:0
in init_mylink, i:1
in init_mylink, i:2
in init_mylink, i:3
in init_mylink, i:4
the 0th inode's value:0
the 1th inode's value:1
the 2th inode's value:2
the 3th inode's value:3
the 4th inode's value:4
add 3...
the 0th inode's value:0
the 1th inode's value:1
the 2th inode's value:2
the 3th inode's value:3
the 4th inode's value:3
the 5th inode's value:4
del 3...
del 3th node in the middle.
del 4th node in the middle.
the 0th inode's value:0
the 1th inode's value:1
the 2th inode's value:2
the 3th inode's value:4
del 0...
del 0th node in the head
the 0th inode's value:1
the 1th inode's value:2
the 2th inode's value:4
begin to free...
free 0th inode success!
free 1th inode success!
free 2th inode success!
五、对单向链表的理解:单向链表相比于双向链表能使用的场景很少。以上是一个用单向链表实现数字排序的算法。相比于数组,单向链表在插入和删除时只需要挪动1,2个指针的指向即可。
六、del_mylink_sort函数中传入了指向指针的指针,目的是为了能直接修改头结点的地址。
七、单向链表最难理解的是每个结点其实有两个地址:一个是自身的地址,一个是指向下一个结点的地址,理解了这个,才能根据画图写出自身指针和next指针之间的赋值。