-单向链表创建、销毁及解决一些问题
定义节点
typedef int data_t;
typedef struct node_t
{
data_t data;
struct node_t *next;
}linknode_t, * linklist_t;
创建链表
/*
*创建带有头结点的单链表,单链表中的数据为键盘输入的数据,键盘输入-1结束
* */
linklist_t CreateLinklist()
{
data_t new_data;
linklist_t head, p_new, p_tmp;
head = (linklist_t)malloc(sizeof(linknode_t));
if (NULL == head)
{
printf("create head node error!\n");
return NULL;
}
p_tmp = head;
scanf("%d", &new_data);
while (-1 != new_data)
{
p_new = (linklist_t)malloc(sizeof(linklist_t));
if (NULL == p_new)
{
printf("create new node error!\n");
break;
}
p_new->data = new_data;
p_tmp->next = p_new;
p_tmp = p_new;
scanf("%d", &new_data);
}
p_tmp->next = NULL;
return head;
}
销毁链表
/*
*销毁单链表
* */
int DestroyLinklist(linklist_t head)
{
int count = 0;
if (NULL == head)
{
return 0;
}
linklist_t p_de = head->next;
while (NULL != p_de)
{
head->next = head->next->next;
count++;
free(p_de);
p_de = head->next;
}
free(head);
head = NULL;
printf("DestroyLinklist count = %d\n", count+1);
return 0;
}
遍历链表
/*
* 遍历链表并输出
* */
void TraverseLinklist(linklist_t head)
{
if (NULL == head || NULL == head->next)
{
printf("DestroyLinklist linklist is empty\n");
return;
}
linklist_t p = head->next;
while(1)
{
printf("%5d", p->data);
if (p->next == NULL)
break;
p = p->next;
}
printf("\n");
}
运行结果展示
单链表在指定位置插入(默认节点下标从0开始,头节点不包括)
/*
*链表的插入,将x插入表中节点i之前
*返回值为0代表插入正确,返回值为-1代表插入失败
* */
int InsertLinklist(linklist_t head, data_t x, int i)
{
linklist_t p_new = NULL, p_before;
int count = 0;
p_before = head;
while (count != i && p_before != NULL)
{
count++;
p_before = p_before->next;
}
if (NULL == p_before)
{
printf("the %d location is error!\n", i);
return -1;
}
else
{
p_new = (linklist_t )malloc(sizeof(linknode_t));
if (NULL == p_new)
{
printf("malloc new node error!\n");
return -1;
}
p_new->data = x;
p_new->next = p_before->next;
p_before->next = p_new;
return 0;
}
}
运行结果展示
结果一:插入位置为末尾
结果一:插入位置正常
结果一:插入位置超出范围
单链表倒置
/*
*链表倒置,使用头插法
* */
void ReverseLinklist(linklist_t head)
{
if (NULL == head || NULL == head->next)
{
printf("ReverseLinklist linklist is empty!\n");
return ;
}
linklist_t p_old = head->next, p_tmp;
head->next = NULL;
while (NULL != p_old)
{
p_tmp = p_old;
p_old = p_old->next;
p_tmp->next = head->next;
head->next = p_tmp;
}
}
运行结果展示
单链表问题一:设结点data域为整型,求链表中相邻两结点data值之和为最大的第一结点的指针
linklist_t AddMax(linklist_t list)
{
if (NULL == list || NULL == list->next)
{
printf("linklist is empty!\n");
return NULL;
}
linklist_t p1 = list->next, p2 = p1->next, p_first = p1;
if (NULL == p2) //只有一个元素
{
return p_first;
}
int max = p1->data + p2->data, tmp = 0;
while (NULL != p2->next)
{
p1 = p2;
p2 = p2->next;
tmp = p1->data + p2->data;
if (tmp > max)
{
max = tmp;
p_first = p1;
}
}
return p_first;
}
运行结果展示
单链表问题二:设两单链表A、B按data值(设为整型)递增有序,设计算法,将表A和B合并成一表A,且表A也按data值递增有序。list1为A,将原来的两个表中的各项依次取出,比较之后按照相应的顺序以尾插法的形式插入到list1中
void Merge(linklist_t list1, linklist_t list2)
{
linklist_t p1 = list1->next, p2 = list2->next, list_tmp = list1;
free(list2);
list2 = NULL;
while (p1 && p2)
{
if (p1->data <= p2->data)
{
list_tmp->next = p1;
list_tmp = p1;
p1 = p1->next;
}
else
{
list_tmp->next = p2;
list_tmp = p2;
p2 = p2->next;
}
}
if (NULL == p1) //收尾
{
p1 = p2;
}
list_tmp->next = p1;
}
结果展示
– 对单链表操作的一些心得
- 想明白链表中的节点定义方式为何是那样
- 明白指针在单链表中的用途,是各个节点之间的“链子”,指针不能乱指,一不小心指错就会导致链表中的节点数据丢失
- 对于链表进行插入等操作,记住:链表的头指针一般情况下不动,通过新增加一个节点指针对链表中的元素进行遍历、插入等操作,如果动头指针,很可能会导致丢失链表中的一些数据(原因如上一条所示)