对于单链表的创建上篇文章我们已经写过了,但是在这还为大家展示一下尾插法创建链表:
首先定义一个头指针,接下来为新的节点开辟空间,并让头指针等于它:
接下来再创建新的节点并让前一个节点变为旧的结点,并让旧节点中的指针指向新节点:
然后就是不断重复上述第二步。
struct notes
{
int n;
struct notes *next;
};
int cnt;//定义一个整型变量用来计算结点的数量
struct notes*create()
{
struct notes *pnew,*pend;
struct notes *phead=NULL;//让头指针指向为空。
cnt = 0;
pnew = pend = (struct notes*)malloc(sizeof (struct notes));
scanf("%d",&pnew->n );//输入第一个元素
while(pnew->n != 0){
cnt++;
if(cnt == 1){
pnew->next = phead;//让第一个元素的下一个节点指向为空
pend = pnew;//让旧结点等于新的结点
phead = pnew;//让头指针指向第一个结点
}else{
pnew->next = NULL;
pend->next = pnew;//让上一个结点指向下一个结点
pend = pnew;
}
pnew=(struct notes*)malloc(sizeof(struct notes));
scanf("%d",&pnew->n );
}
free(pnew);//释放数据为零的空间
return phead;//返回头指针
}
//创建函数用来遍历链表
void print(struct notes*phead)
{
struct notes *ptemp;//定义一个临时指针用来输出元素
ptemp = phead;//让临时指针等于头指针
//开始循环输出
while(ptemp != NULL){
printf("%d\n",ptemp->n );
ptemp = ptemp->next ;//让元素自身等于它指向的下一个元素
}
}
链表的创建与遍历就到此为止了,接下来就是链表其他的基础操作。
1,链表的插入(增);
(1)在链表头部插入新节点:
struct notes *SListPushFront(struct notes *phead)
{
struct notes *pnew;//定义需要插入的节点
pnew=(struct notes*)malloc(sizeof(struct notes));//开辟空间
scanf("%d",&pnew->n );//输入新值
pnew->next = phead;//让新节点指向原来的头结点
phead=pnew;//让头结点等于新插入的结点
return phead;//返回新节点
}
(2)在链表的第k个值前插入:
在第k个值前插入首先得让链表进行遍历并让遍历在第k个值时停止。
void AddListbeforek(struct notes *phead)
{
int k;
scanf("%d",&k);//输入k的值。
struct notes *pnew;
pnew = (struct notes*)malloc(sizeof(struct notes));
scanf("%d",&pnew->n);
int i;
struct notes *p;//创建临时结点,用来存储第k-1个结点。
struct notes *ptemp;//创建一个临时结点用来遍历第k个结点之前的元素。
for(i=1;i<=k;i++){
p = ptemp;//让p等于当前ptemp的结点 。
ptemp = ptemp->next;//当循环停止时,ptemp刚好为第k个结点。
}
p->next = pnew;//让原来第k-1个结点指向新结点。
pnew->next = ptemp; //让新节点指向第k个结点。
}
当然,在头部插入和在第k个值前插入是可以在一个函数里完成的,但是函数类型就变为了结构体指针类型了,需要返回其头指针。
struct notes *AddListbeforek(struct notes *phead)
{
int k;
scanf("%d",&k);
struct notes *pnew;
pnew = (struct notes*)malloc(sizeof(struct notes));
scanf("%d",&pnew->n);
//判断k是否等于1。
if(k==1){
pnew->next = phead;
phead = pnew;
return phead;
}
//如果不等于1,进行接下来的步骤。
int i;
struct notes *p;//创建临时结点,用来存储第k-1个结点。
struct notes *ptemp;//创建一个临时结点用来遍历第k个结点之前的元素。
for(i=1;i<=k;i++){
p = ptemp;//让p等于当前ptemp的结点 。
ptemp = ptemp->next;//当循环停止时,ptemp刚好为第k个结点。
}
p->next = pnew;//让原来第k-1个结点指向新结点。
pnew->next = ptemp; //让新节点指向第k个结点。
return phead;
}
(3)在尾部插入新结点,需要链表遍历至最后一个结点。
void PushBack(struct notes *phead)
{
struct notes *pnew;
pnew = (struct notes *)malloc(sizeof(struct notes));
scanf("%d",&pnew->n);
pnew->next = NULL;//让新结点的指向为空
struct notes *ptemp;//创建临时结点,用来遍历至尾结点。
ptemp = phead;
while(ptemp->next = NULL){//当遍历至尾结点时停止
ptemp = ptemp->next;
}
ptemp->next = pnew;//让原来的尾结点指向加入的结点,使新节点变为尾结点。
}
2,删除指定结点,也需要遍历至k结点,并让k-1指向k+1。
如:删除第k个结点:
node *DeleteListTail(node *phead)
{
node *ptemp;//临时结点,用来遍历链表。
ptemp = phead;
int k;
scanf("%d",&k);//输入k的值。
if(k==1){//如果删除第一个结点,则执行。
phead = ptemp->next;
free(ptemp);
return phead;
}
int i=1;
node *l;//临时结点,用来存储k-1的元素。
while(i!=k){
l = ptemp;
ptemp = ptemp->next;
i++;
}
if(ptemp->next == NULL){//判断是否删除最后一个节点
free(ptemp);
l->next = NULL;
return phead;//返回第k-1个结点。
}
l->next = ptemp->next;//让k-1指向k+1。
free(ptemp);//释放第k个结点的空间。
return phead;
}
3.改变第k个结点的值。
void gai(node *phead)
{
node *ptemp;
ptemp = phead;
int i=1,k;
scanf("%d",&k);
while(i!=k){
ptemp = ptemp->next;
}
scanf("%d",&ptemp->n);
}
4,查询第k个结点;
和改变某一节点的值相似,但是没有输入结点元素值的部分。
void gai(node *phead)
{
node *ptemp;
ptemp = phead;
int i=1,k;
scanf("%d",&k);
while(i!=k){
ptemp = ptemp->next;
}
printf("%d",ptemp->n);
}