单链表不带头标准c语言实现
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。
下面给出不带头的单链表标准实现:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} Node;
void pushBackList(Node *list, int data) //尾插
{
Node *head = list;
Node *newNode = (Node *)malloc(sizeof(Node)); //申请空间
newNode->data = data;
newNode->next = NULL;
if (list == NULL) //为空
list = newNode;
else //非空
{
while (head->next != NULL)
head = head->next;
head->next = newNode;
}
}
/* 初始条件:链式线性表L已存在。操作结果:返回L中数据元素个数 */
int sizeList(Node *list)
{
int i = 0;
Node *p = list->next; /* p指向第一个结点 */
while (p)
{
i++;
p = p->next;
}
return i;
}
int insertList(Node *list, int index, int data) //插入
{
int n;
int size = sizeList(list); //获取链表长度
Node *head = list;
Node *newNode, *temp;
if (index < 0 || index > size)
return 0; //非法,要插入的位置小于0,大于链表长度
newNode = (Node *)malloc(sizeof(Node)); //创建新节点
newNode->data = data;
newNode->next = NULL;
if (index == 0) //头插
{
newNode->next = head;
list = newNode;
return 1;
}
for (n = 1; n < index; n++) //非头插
head = head->next;
if (index != size)
newNode->next = head->next;
//链表尾部next不需指定
head->next = newNode;
return 1;
}
void deleteList(Node *list, int data) //按值删除
{
Node *head = list;
Node *temp;
while (head->next != NULL)
{
if (head->next->data != data)
{
head = head->next;
continue;
}
temp = head->next;
if (head->next->next == NULL) //尾节点删除
head->next = NULL;
else
head->next = temp->next;
free(temp);
}
head = list;
if (head->data == data) //头结点删除
{
temp = head;
list = head->next;
head = head->next;
free(temp);
}
}
int printList(Node *list) //打印
{
if (list->next == NULL)
{
printf("打印 \n");
return 0;
}
Node *temp = list->next;
for (; temp != NULL; temp = temp->next)
printf("%d ", temp->data);
printf("\n");
return 1;
}
int freeList(Node *list) //清空
{
/*
暂时未知
*/
// Node *head = list;
// Node *temp = NULL;
// printf("666");
// while (head != NULL) //依次释放
// {
// temp = head;
// head = head->next;
// free(temp);
// }
list->next = NULL; //置空
printf("清空\n");
return 0;
}
int main(void) //测试
{
Node *head;
for (int i = 0; i < 10; i++)
{
pushBackList(head, i);
}
insertList(head, 10, 10);
insertList(head, 5, 10);
printList(head);
deleteList(head,10);
printList(head);
int a = freeList(head);
printf("%d \n", a);
printList(head);
}
运行结果
0 1 2 3 10 4 5 6 7 8 10
0 1 2 3 4 5 6 7 8
清空
0
打印
别的也没啥了,都是基本操作 有些代码要分情况,很麻烦,可读性较强吧
单链表不带头压缩c语言实现
注:单追求代码简洁,所以写法可能有点不标准。
//第一次拿c开始写数据结构,因为自己写的,追求代码量少,和学院ppt不太一样。有错请指出
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node//定义节点
{
int data;
struct node * next;
}Node;
//函数介绍
void printlist(Node * head);//打印链表
int lenlist(Node * head);//返回链表长度
void insertlist(Node ** list,int data,int index);//插入元素
void pushback(Node ** head,int data);//尾部插入
void freelist(Node ** head);//清空链表
void deletelist(Node ** list,int data);//删除元素
Node * findnode(Node ** list,int data);//查找
void change(Node ** list,int data,int temp);//改变值
void printlist(Node * head)//打印链表
{
for(;head!=NULL;head=head->next) printf("%d ",head->data);
printf("\n");//为了其他函数打印,最后换行
}
int lenlist(Node * head)//返回链表长度
{
int len;
Node * temp = head;
for(len=0; temp!=NULL; len++) temp=temp->next;
return len;
}
void insertlist(Node ** list,int data,int index)//插入元素,用*list将head指针和next统一表示
{
if(index<0 || index>lenlist(*list))return;//判断非法输入
Node * newnode=(Node *)malloc(sizeof(Node));//创建
newnode->data=data;
newnode->next=NULL;
while(index--)list=&((*list)->next);//插入
newnode->next=*list;
*list=newnode;
}
void pushback(Node ** head,int data)//尾插,同上
{
Node * newnode=(Node *)malloc(sizeof(Node));//创建
newnode->data=data;
newnode->next=NULL;
while(*head!=NULL)head=&((*head)->next);//插入
*head=newnode;
}
void freelist(Node ** head)//清空链表
{
Node * temp=*head;
Node * ttemp;
*head=NULL;//指针设为空
while(temp!=NULL)//释放
{
ttemp=temp;
temp=temp->next;
free(ttemp);
}
}
void deletelist(Node ** list,int data)//删除链表节点
{
Node * temp;//作用只是方便free
while((*list)->data!=data && (*list)->next!=NULL)list=&((*list)->next);
if((*list)->data==data){
temp=*list;
*list=(*list)->next;
free(temp);
}
}
Node * findnode(Node ** list,int data)//查找,返回指向节点的指针,若无返回空
{
while((*list)->data!=data && (*list)!=NULL) list=&((*list)->next);
return *list;
}
void change(Node ** list,int data,int temp)//改变
{
while((*list)->data!=data && (*list)->next!=NULL)list=&((*list)->next);
if((*list)->data==data)(*list)->data=temp;
}
int main(void)//测试
{
Node * head=NULL;
Node ** gg=&head;
int i;
for(i=0;i<10;i++)pushback(gg,i);
printf("链表元素依次为: ");
printlist(head);
printf("长度为%d\n",lenlist(head));
freelist(gg);
printf("释放后长度为%d\n",lenlist(head));
for(i=0;i<10;i++)pushback(gg,i);
deletelist(gg,0);//头
deletelist(gg,9);//尾
deletelist(gg,5);
deletelist(gg,100);//不存在
printf("再次创建链表,删除节点后\n");
printlist(head);
freelist(gg);
for(i=0;i<5;i++)pushback(gg,i);
insertlist(gg,5,0);//头
insertlist(gg,5,5);
insertlist(gg,5,7);//尾
insertlist(gg,5,10);//不存在
printlist(head);
printf("找到%d\n把3变为100",*findnode(gg,5));
change(gg,3,100);
change(gg,11111,1);//不存在
printlist(head);
}
运行结果
链表元素依次为: 0 1 2 3 4 5 6 7 8 9
长度为10
释放后长度为0
再次创建链表,删除节点后
1 2 3 4 6 7 8
5 0 1 2 3 5 4 5
找到6422000
把3变为1005 0 1 2 100 5 4 5