1.初始化
2. 求表长
3.按位查找结点
4.按值查找节点
5.后插
6.前插
7.删除
8.头插法新建单链表
9.尾插法新建单链表
10.链表逆置
11.主函数
12.总代码
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
//单链表的初始化
bool InitList(LinkList &L)
{
L= (LNode*)malloc(sizeof(LNode));
L->next=NULL;
return true;
}
//求单链表的表长
int Length(LinkList L)
{
int i=0;
LNode *p=L->next;
while(p!=NULL)
{
p=p->next;
i++;
}
return i;
}
//按序号查找表节点 返回的是节点的指针
LNode* GetElem(LinkList L,int i)
{
LNode *p=L->next;
int j=1;
while(p!=NULL && j<i)
{
p=p->next;
j++;
}
return p;
}
//按照值查找表节点
LNode* LocateElem(LinkList L,int e)
{
LNode *p=L->next;
while(p!=NULL && p->data!=e)
{
p=p->next;
}
return p;
}
//前插与后插:比如说有1 2 3 4 5 五个数,要插入一个数字在第三个数字的位置,后插操作是在第二个位置的后面进行插入
//而前插则是在插到第四个位置,然后将第四个位置的数据域和第三个位置的数据域换一下,偷偷地实现前插
//后插入某一个结点
bool After_InsertList(LinkList &L,int i,int e)
{
LNode *p = GetElem(L,i-1); //后插操作,首先要先找到第i-1个结点
if(p==NULL)
return false; //如果插入的位置不合法,返回false
else
{
LNode *s = (LNode*) malloc(sizeof (LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
}
//前插入某一个结点 思想是将 待插入的结点插入到已知结点的后面,而后交换数据域的部分,实现前插
bool Before_InsertList(LinkList &L,int i,int e)
{
LNode *p = GetElem(L,i);
if(p==NULL)
return false;
else
{
LNode *s = (LNode*) malloc(sizeof (LNode));
s->next=p->next;
p->next = s ;
s->data=p->data;
p->data=e;
return true;
}
}
//删除某一结点 删除的结点的值要带回主函数
bool DeleteList(LinkList &L,int i,int &e)
{
LNode *p= GetElem(L,i-1); //要删除结点的前一个结点
if(p==NULL || p->next==NULL)
return false;
LNode *dep=p->next; //dep是要删除的结点
e=dep->data;
p->next=dep->next;
free(dep);
return true;
}
//删除某一确定的结点*p
bool Delete2List(LNode *p)
{
if(p==NULL)
return false;
if(p->next==NULL)
{
//这样的话如果要删除的p结点是最后一个的话,
// 那么afp->next 就可能出现空指针的错误,所以要加个判断
//这时如果要删除的话,则需要从表头依次遍历找到前一个结点
}
LNode *afp=p->next; //afp 是指p的后继结点
p->data=afp->data;
p->next=afp->next;
free(afp);
return true;
}
//头插法新建单链表
LinkList List_HeadInsert(LinkList &L)
{
L=(LinkList) malloc(sizeof (LinkList));
L->next=NULL;
LNode *s;
int e;
scanf("%d",&e);
while(e!=9999)
{
s=(LNode*) malloc(sizeof (LNode));
s->data=e;
s->next=L->next;
L->next=s;
scanf("%d",&e);
}
return L;
}
//尾插法新建单链表
LinkList List_TailInsert(LinkList &L)
{
L=(LNode*) malloc(sizeof(LNode));
LNode *p,*s;
p=L;
int e;
scanf("%d",&e);
while(e!=9999)
{
s=(LNode*) malloc(sizeof(LNode));
s->data=e;
p->next=s;
p=p->next;
scanf("%d",&e);
}
s->next=NULL;
return L;
}
//打印单链表的函数
void PrintList(LinkList L)
{
LNode *p=L->next;
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
//链表的逆置
//迭代法设置三个指针实现
LinkList Iterate_InversionList(LinkList &L)
{
LNode *begin,*mid,*end;
begin=NULL;
mid=L->next;
end=mid->next;
while(1)
{
mid->next=begin;
if(end==NULL)
break;
begin=mid;
mid=end;
end=end->next;
}
L->next=mid;
return L;
}
//头插法实现链表的逆置 这里使用了一个新的头结点用来原链表上摘下的结点
LinkList Head_InversionList(LinkList &L)
{
LinkList LL=(LNode*) malloc(sizeof(LNode)); //LL表示逆置后的链表
LL->next=NULL;
LNode *p=L->next,*temp;
while(p!=NULL)
{
temp=p; //摘除结点:使用一个临时结点存下来
p=p->next;
temp->next=LL->next;
LL->next=temp;
}
return LL;
}
//就地逆置法实现 思想和头插法类似,就地对原链表进行修改
LinkList NoAddList_InversionList(LinkList &L)
{
LNode *begin,*end;
begin=L->next;
end=begin->next;
while(end!=NULL)
{
begin->next=end->next;
end->next=L->next;
L->next=end;
end=begin->next;
}
return L;
}
int main() {
LinkList L;
InitList(L);
//List_HeadInsert(L);
//PrintList(L);
List_TailInsert(L);
PrintList(L);
printf("The length of LinkList: %d\n", Length(L));
After_InsertList(L,3,56); //后插
PrintList(L);
Before_InsertList(L,2,89); //前插
PrintList(L);
int e;
DeleteList(L,6,e); //删除
PrintList(L);
printf("The deleted element:%d\n",e);
Iterate_InversionList(L); //迭代实现链表逆置
PrintList(L);
NoAddList_InversionList(L); // 原地对原链表逆置
PrintList(L);
LinkList newL=Head_InversionList(L); //这个函数中使用了一个新的头结点用来原链表上摘下的结点,所以L会变化
PrintList(newL);
PrintList(L);
return 0;
}
//测试数据: 7 8 6 3 1 2 9999
13.测试结果
注:本文为借鉴别的文章后,自己动手所写的内容,仅供学习参考,欢迎批评指正,学习交流!