#include <stdio.h>
#include <stdlib.h>
//本代码的链表是带表头链表,首节点(即表头)不算是元素
struct list
{
int data;//数据域
struct list *next;//指针域,指向下一个节点的地址
};
struct list *create_list()//建立一个链表
{
// struct list *p = (struct list*)malloc(sizeof(struct list));
// p->data = 0;
// p->next = NULL;
// return p;
return calloc(sizeof(struct list),1);//分配sizeof(struct list)个长度为1的堆内存空间,并自动清零
}
void traverse(struct list *ls)//循环遍历链表
{
struct list *p = ls;
while(p)
{
printf("%d\n",p->data);
p = p->next;
}
}
struct list *insert_list(struct list *ls, int n, int data)//在指定位置插入元素
{
struct list *p = ls;
while(p && n--)
{
p = p->next;
}
if(!p)//有可能链表长度只有5,但是用户却要在100的位置插入数据
return NULL;
else
{
struct list *node = create_list();//创建一个新的节点
node->data = data;
node->next = p->next;
p->next = node;
return node;
}
}
int delete_list(struct list *ls, int n)//删除指定位置元素
{
struct list *p = ls;
while(p && --n)//这里用--n是为了while过后,指针指向指定位置的前节点,因为链表无法回头
{
p = p->next;
}
if(!p)
return 0;
else
{
struct list *node = p->next;//使用指针指向要删除的节点位置
if(!node)//如果节点位置无效
return 0;
else
{
p->next= node->next;
free(node);
return 1;
}
}
}
int count_list(struct list *ls)//返回链表元素个数(不包含首节点)
{
int count = 0;
struct list *p = ls->next;
while(p)
{
count++;
p = p->next;
}
return count;
}
void clear_list(struct list *ls)//清空链表,只保留首节点
{
struct list *p = ls->next;
while(p)
{
struct list *tmp = p->next;//临时保留下个节点的地址
free(p);//释放当前节点
p = tmp;//把p指向下个节点
}
ls->next = NULL;//把首节点的指针指向空
}
int empty_list(struct list *ls)//返回链表是否为空
{
if(ls->next)//如果首节点后还有节点,说明链表不为空
return 1;
else
return 0;
}
struct list *locale_list(struct list *ls, int n)//返回链表指定位置的节点(不包含首节点)
{
struct list *p = ls->next;
while(p && n--)
{
p = p->next;
}
return p;
}
struct list *elem_locale(struct list *ls, int data)//返回数据域等于data的节点
{
//这是我自己的做法
// struct list *p = ls->next;
// while(ls->data!=data)
// {
// p = p->next;
// }
// if(p)
// return p;
// else
// return NULL;
//这是别人的做法
struct list *p = ls->next;
while(p)
{
if(p->data == data)
break;
p = p->next;
}
return p;
}
int elem_pos(struct list *ls, int data)//返回数据域等于data的节点位置
{
struct list *p = ls->next;
int index = 0;
while(p)
{
if(p->data == data);
break;
p = p->next;
index++;
}
return index;
}
struct list *last_list(struct list *ls)//得到链表的最后一个节点
{
//这是我自己的做法
// struct list *p = ls->next;
// while(p->next)
// {
// p = p->next;
// }
// return p;
//这是别人的做法
struct list *p = ls->next;
struct list *pre = p;
while(p)
{
pre = p;
p = p->next;
}
return pre;
}
void merge_list(struct list *ls1,struct list *ls2)//合并两个链表,结果放入ls1中
{
struct list *p = last_list(ls1);
p->next = ls2->next;
free(ls2);
}
void reverse_list(struct list *ls)//逆置链表
{
if(!ls->next)
return;//只有首节点,不需要逆置
if(!ls->next->next)
return;//除了首节点,就一个有有效节点
struct list *pre = ls;//前一个节点的指针
struct list *cur = ls->next;//当前节点的指针
struct list *next = NULL;//指向下一个节点的指针
struct list *last = ls->next;//因为逆置完成后,首节点的next就成了最后一个节点
while(cur)
{
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
last->next = NULL;
ls->next = pre;
}
int main(void)
{
struct list *first = create_list();//创建链表的首节点
struct list *second = create_list();//创建下一个节点
second->data = 2;
struct list *third = create_list();
third->data = 3;
first->next = second;//关联2个节点
second->next = third;
// first->next = third;//移除第二个节点,实际上就是把首节点的指针指向第三个节点,然后释放第二个节点
// free(senond);
int i;
for(i = 0;i<10;i++)
{
insert_list(first,i,i);//在指定位置插入指定数据
}
// delete_list(first,3);//删除第4个节点
// clear_list(first);//清空链表
traverse(first);//循环遍历节点
// printf("list[4] = %d\n",locale_list(first,4)->data);
// printf("where data equals 4 : %d\n",locale_list(first,4)->data);
// printf("count of list = %d\n",count_list(first));
printf("the last elem is : %d\n",last_list(first)->data);
return 0;
}
c语言数据结构——链表常用算法
最新推荐文章于 2024-07-26 18:45:14 发布