链表(Linked list)是一种线性表,但是并不会在物理存储上按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表的插入和删除操作可以达到O(1)的复杂度

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
typedef int data_t;//将int类型用data_t代替
//构造链表节点类型
typedef struct node{
data_t data;//数据域: 保存链表元素的数值
struct node* next;//指针域: 保存链表下一个节点的地址
}linklist;
//创建空链表,即链表中只有头节点
linklist *createLinklist(void)
{
linklist *head = (linklist *)malloc(sizeof(linklist));//给结构体开空间
if(NULL == head)
return NULL;
head->data = -1;//表示data域无效
head->next = NULL;
return head;
}
//判断链表是否为空
int linklist_is_empty(linklist *head)
{
if(NULL != head)
return ((head->next == NULL) ? 1: 0);
}
//求链表中节点个数
int getLengthLinklist(linklist *head)
{
if(NULL == head)
return -1;
int num = 0;
linklist *p = head->next;//p指针指向第一个有效节点
while(p != NULL)
{
num++;
p = p->next;
}
return num;
}
//按位置添加节点
/************************************************************
Descrption:按位置添加节点
int insertLinklistByPos(linklist *head, int pos, data_t data)
Argument:
head:链表头节点的地址
pos:要插入节点的地址 pos:从0开始
data:要插入节点的data值
Return:
成功:0
失败:-1
************************************************************/
int insertLinklistByPos(linklist *head, int pos, data_t data)
{
if(NULL== head)
return -1;
int len = getLengthLinklist(head);//得到链表节点的个数
//判断位置是否有效
if(pos < 0 || pos > len)//有效位置为 0 ~ len
return -1;
//给新节点开空间
linklist *new = (linklist *)malloc(sizeof(linklist));
new->data = data;//将要插入的data值赋给新节点的data
new->next = NULL;
linklist *p = head;
//找到pos-1位置处节点的地址
while(pos--)
p = p->next;
//将新节点插入到p节点之后
new->next = p->next;
p->next = new;
return 0;
}
//按位置删除链表中节点
/**********************************************
Description:按位置删除链表中节点
int deleteLinklistByPos(linklist *head, int pos)
Argument:
head:链表头节点的地址
pos:指定要删除节点的位置
Return:
成功:0
失败:-1
**********************************************/
int deleteLinklistByPos(linklist *head, int pos)
{
if(NULL == head)
return -1;
//判空
if(linklist_is_empty(head))
return -1;
int len = getLengthLinklist(head);
//判断位置是否有效
if(pos < 0 || pos > len-1)//有效位置为 0 ~ len-1
return -1;
linklist *p = head;
while(pos--) //找到 pos-1 位置处节点的地址
p = p->next;
linklist *q = p->next;//q指针用来保存要删除节点的地址
p->next = q->next;//将q节点的前一个节点和后一个节点连接
free(q);
q = NULL;
return 0;
}
//按值删除节点
int deleteLinklistByData(linklist *head, data_t data)
{
if(NULL == head)
return -1;
if(linklist_is_empty(head))
return -1;
linklist *p = head;
linklist *q = NULL;
while(p->next != NULL)
{
if(p->next->data == data)
{
q = p->next;
p->next = q->next;
free(q);
q = NULL;
}
else
p = p->next;
}
return 0;
}
//按值查找节点,返回节点的地址
/*******************************************************
Descrption:按值查找节点,返回节点的地址
linklist *findLinklistByData(linklist *head, data_t data)
Argument:
head:链表头节点的地址
data:要查找的节点的data值
Return:
成功:查找到的值为data的节点的地址
失败:NULL
*******************************************************/
linklist *findLinklistByData(linklist *head, data_t data)
{
if(NULL == head)
return NULL;
if(linklist_is_empty(head))//判空
return NULL;
linklist *p = head->next;//p指针指向第一个有效节点
while(p != NULL)//循环遍历整个链表
{
if(p->data == data)//比较链表节点的值是否为 data
return p;
else
p = p->next;
}
return NULL;
}
//按位置查找
data_t findLinklistByPos(linklist *head, int pos)
{
if(head == NULL)
return -1;
int len = getLengthLinklist(head);
if(pos < 0 || pos > len-1)
return -1;
linklist *p = head->next;
while(pos--) //p指向pos位置节点
p = p->next;
return (p->data);
}
//按位置修改链表节点的值
int changeLinklistByPos(linklist *head, int pos, data_t data)
{
if(NULL == head)
return -1;
int len = getLengthLinklist(head);
if(pos < 0 || pos > len-1)
return -1;
linklist *p = head->next;
while(pos--)
p = p->next;
p->data = data;
return 0;
}
//按值修改链表节点的值
int changeLinklistByData(linklist *head, data_t old, data_t new)
{
linklist *p = findLinklistByData(head, old);
if(NULL == p)
return -1;
p->data = new;
return 0;
}
//清空链表
int clearLinklist(linklist *head)
{
if(NULL == head)
return -1;
linklist *p = head->next;
head->next = NULL;
linklist *q = NULL;
while(p != NULL)
{
q = p->next;//q保存p的下一个节点的地址
free(p);
p = q;
}
return 0;
}
//销毁链表
void destoryLinklist(linklist **head)
{
clearLinklist(*head);
free(*head);
*head = NULL;
}
//链表的逆序 基于头节点的插入 重点
int reverseLinklist(linklist *head)
{
if(NULL == head)
return -1;
linklist *p = head->next;
head->next = NULL;
linklist *q = NULL;
while(p != NULL)
{
q = p->next;
p->next = head->next;
head->next = p;
p = q;
}
return 0;
}
//打印链表中各个节点的data值
void printLinklist(linklist *head)
{
if(NULL == head)
return;
linklist *p = head->next;//p指针指向第一个有效节点
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
return ;
}
//主函数
int main()
{
linklist *head = createLinklist();
if(NULL == head)
{
printf("malloc failed\n");
return -1;
}
int i=0;
while(i<10)
{
insertLinklistByPos(head, i, i+1);
i++;
}
printLinklist(head);
i=0;
while(i < 5)
{
deleteLinklistByPos(head, 0);
i++;
}
printLinklist(head);
linklist *p = findLinklistByData(head, 8);
if(NULL == p)
{
printf("No find data\n");
return -1;
}
printf("p->data=%d\n",p->data);
changeLinklistByPos(head, 1, 100);
printLinklist(head);
changeLinklistByData(head, 100, 7);
printLinklist(head);
reverseLinklist(head);
printLinklist(head);
return 0;
}