一.前言
对于单向链表,除了常规的建立、插入结点、删除结点、遍历等,此处加入了排序、去重、颠倒等较高级的功能,代码放在下面,比较好理解,可以直接copy运行一下的。实际做实验的时候用不到这么多功能,可以自选几个去用。在这简单对几个函数进行一下说明:
去重:刚开始的时候,用指针p指向链表第一个元素,让Phead->next指向空,这一步实际是把链表一分为二了,再用一个q指向包含头结点的那部分的第一个元素。然后进行循环,每循环一次,p往右走一步,直到走到那部分的尽头。每次循环都做什么呢?每次循环都要检查p此时指向的元素的值和包含头结点那部分的链表有没有重复元素,即设置循环:while(q&&q->data!=p->data)q=q->next;,结局有两个,一是q为null,此时说明没有重复的,利用头插法把p指向的元素插入phead后面,另外一种结局是data相同,此时说明元素重复,则直接free(p)
颠倒:由于去重本质是头插法构造,所以最后元素是反的,那么我们可以再利用“分割链表”这个思想去把元素颠倒过来,所以这个函数的代码与去重几乎一样
排序:这个实际就是一个普通的冒泡排序(当然也可以用其它的)只不过i的初始化相当于p指向第一个元素,i++相当与p=p->next
下面是c语言代码,所有代码为本人手打,如果有错误或不足,还请在评论区指正 ◟̆◞̆♡
二.c代码
前期准备和主函数:
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
typedef struct Node{
int data;
struct Node *next;
}Node,*pNode;
pNode CreatList(void);//创建
void ClearList(pNode);//
void TraverseList(pNode);//遍历
int GetElem(pNode,int);//求某个元素的值
int ListLength(pNode);//求长度
bool is_empty(pNode);//是否为空
void SortList(pNode);//排序 (原理:选择排序
void PurgeList(pNode);//去重 ,本质:头插(缺陷:会使链表颠倒,要么 改为尾插,要么利用颠倒函数
bool ListDelete(pNode,int);
bool ListInsert(pNode,int,int);//插入元素
void ListReverse(pNode);//链表翻转,思想为与去重函数类似的分割 ,然后两边指针扫描
//ClearList,ListDelete,ListInsert的工作指针都是指向目标位置的前驱 ,比如初始把工作指针指向头结点而非第一个元素
int main()
{
pNode pHead;
int i;
pHead=CreatList();
TraverseList(pHead);
printf("请输入您需要第几个元素(数字):");
scanf("%d",&i);
printf("第%d个数字为%d\n",i,GetElem(pHead,i));
PurgeList(pHead);
printf("去重之后链表内容为:\n");
TraverseList(pHead);
ListReverse(pHead);
printf("颠倒之后的链表内容:\n");
TraverseList(pHead);
SortList(pHead);
printf("排序之后链表内容:\n");
TraverseList(pHead);
ClearList(pHead);
printf("清空后的结果:\n");
if(is_empty(pHead))
printf("成功清空!\n");
return 0;
}
函数定义大全:
pNode CreatList(void)//尾插法
{
pNode pHead=(pNode)malloc(sizeof(Node));
if(pHead==NULL)
{
printf("no memory\n");
exit(1);
}
int i,val,len;
printf("输入您需要的链表长度:");
scanf("%d",&len);
pNode pTail=pHead;
pTail->next=NULL;
for(i=1;i<=len;i++)
{
pNode pNew=(pNode)malloc(sizeof(Node));
if(pNew==NULL)
{
printf("no memory\n");
exit(1);
}
printf("请输入第%d个数据:",i);
scanf("%d",&val);
pNew->data=val;
pTail->next=pNew;
pNew->next=NULL;
pTail=pNew;
}
return pHead;
}
int ListLength(pNode pHead)
{
int len=0;
pNode p=pHead->next;
while(p)
{
len++;
p=p->next;
}
return len;
}
void TraverseList(pNode pHead)
{
pNode p=pHead->next;
while(p)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
return;
}
int GetElem(pNode pHead,int i)
{
pNode p=pHead->next;//指向第一个元素
int j=1;
while(j<i)
{
p=p->next;
j++;
}
return p->data;
}
bool is_empty(pNode pHead)
{
if(pHead->next==NULL)
return true;
else
return false;
}
void PurgeList(pNode pHead)
{
pNode p,q,succ;
p=pHead->next;
pHead->next=NULL;
while(p)
{
q=pHead->next;
succ=p->next;
while(q&&q->data!=p->data)q=q->next;
if(q==NULL)
{
p->next=pHead->next;
pHead->next=p;
}
else free(p);
p=succ;
}
return;
}
void ListReverse(pNode pHead)
{
pNode p,succ;
p=pHead->next;
pHead->next=NULL;
while(p)
{
succ=p->next;
p->next=pHead->next;
pHead->next=p;
p=succ;
}
return;
}
void SortList(pNode pHead)
{
int i,j,t,len=ListLength(pHead);
pNode p,q;
for(i=1,p=pHead->next;i<len;i++,p=p->next)
{
for(j=i+1,q=p->next;j<=len;j++,q=q->next)
{
if(p->data>q->data)
{
t=p->data;
p->data=q->data;
q->data=t;
}
}
}
}
bool ListInsert(pNode pHead,int i,int e)
{
if(i<=0||i>ListLength(pHead))
{
printf("您输入的位置有问题\n");
return false;
}
pNode pNew=(pNode)malloc(sizeof(Node));
if(pNew==NULL)
{
printf("no memory\n");
return false;
}
pNew->data=e;
pNode p=pHead;
int j=1;
while(j<i)
{
p=p->next;
j++;
}
pNew->next=p->next;
p->next=pNew;
return true;
}
bool ListDelete(pNode pHead,int i)
{
if(i<=0||i>ListLength(pHead))
{
printf("您输入的位置有问题\n");
return false;
}
int j=1;
pNode p=pHead;
while(j<i)
{
p=p->next;
j++;
}
pNode q;
q=p->next;
p->next=q->next;
free(q);
return true;
}
void ClearList(pNode pHead)
{
pNode p;
p=pHead->next;
while(p!=NULL)
{
pHead->next=p->next;
free(p);
p=pHead->next;
}
return;
}
三. 效果