单链表相关知识以及指针引用相关知识

#include<stdio.h>
#include<malloc.h>
typedef char ElemType;
typedef struct LNode
{
ElemType data; //
struct LNode *next; //指针占4个字节
}LinkNode; //声明单链表节点类型
/*************************************/
/*
头插法相对简便,但插入的数据与插入的顺序相反;
尾插法操作相对复杂,但插入的数据与插入顺序相同。

头插法创建链表时候,就相当于后来居上。
后面的结点不断往前插,而最后创建的结点在第一个结点处, 第一个创建的结点变成了尾结点。

尾插法相当于不断开创新的结点,
然后不断将新的结点的地址当做尾结点。尾结点不断后移,而新创的结点时按照创建的先后顺序而连接的。
*/
void CreateListF(LinkNode *&L,ElemType a[],int n)//头插法建立单链表
{
LinkNode *s;
L=(LinkNode *)malloc(sizeof(LinkNode));//创建头节点
L->next=NULL;
for(int i=0;i<n;i++)
{
s=(LinkNode *)malloc(sizeof(LinkNode));//创建新节点
s->data=a[i];
s->next=L->next; //将节点s插在原开始节点之前,头节点之后
L->next=s;
}
}
void CreateListR(LinkNode *&L,ElemType a[],int n)//尾插法建立单链表
{
LinkNode *s,*r;
L=(LinkNode *)malloc(sizeof(LinkNode));//创建头节点
L->next=NULL;
r=L; //r始终指向尾节点,开始时指向头节点
for(int i=0;i<n;i++)
{
s=(LinkNode *)malloc(sizeof(LinkNode));//创建新节点
s->data=a[i];
r->next=s;//将节点s插入r节点之后
r=s; //再将指针r指向s,即将r指向了尾节点
}
r->next=NULL;//尾节点next域置为NULL
}
void InitList(LinkNode *&L)//初始化线性表
{
L=(LinkNode *)malloc(sizeof(LinkNode));//创建头节点
L->next=NULL; //将单链表置为空表
}
void DestoryList(LinkNode *&L)//销毁单链表
{
LinkNode *pre=L,*p=pre->next;
while(p!=NULL)
{
free(pre);
pre=p; //pre、p同步后移一个位置,pre指向p节点的前一个节点,即p是pre的下一个节点
p=pre->next;
}
free(pre); //此时p为NULL,pre指向尾节点,释放它
}
bool ListEmpty(LinkNode *L)//判断线性表是否为空表
{
return(L->next==NULL);
}
int ListLength(LinkNode *L)//求线性表的长度
{
int i=0;
LinkNode *p=L;
while(p->next!=NULL) //p指向头节点,i置为0(即头节点的序号为0)
{
i++;
p=p->next;
}
return(i); //循环结束,p指向尾节点,其序号i为节点个数
}
void DispList(LinkNode *L)//输出线性表
{
LinkNode *p=L->next;//p指向第一个节点,不是头节点
while(p!=NULL)
{
printf("%c",p->data);//如果p不为NULL,输出其data域
p=p->next;//p移向下一个节点
}
printf("\n");
}
bool GetElem(LinkNode *L,int i,ElemType &e)//求线性表中第i个元素的位置
{
int j=0;
LinkNode *p; //p指向头节点,j置为0(即头节点序号为0)
p=L;
if(i<=0)return false;//i错误,返回假
while(j<i&&p!=NULL) //找到第i个节点
{
j++;
p=p->next;
}
if(p==NULL)//不存在第i个数据节点,返回false
{
return false;
}
else //存在第i个节点
{
e=p->data;
return true;
}
}
int LocateElem(LinkNode *L,ElemType e) //查找元素e在线性表中的位置
{
int i=1;
LinkNode *p=L->next;//p指向首节点,i置为1(即首节点的序号为1)
while(p!=NULL&&p->data!=e)//进行定位,查找data值为e的节点,其序号为i
{
p=p->next;
i++;
}
if(p==NULL) //不存在值为e的节点
{
return false;
}
else
{
return i;
}
}
bool ListInsert(LinkNode *&L,int i,ElemType m) //插入第i个元素
{
int j=0;
LinkNode *p=L,*s;
if(i<0)return false;
while(j<i-1&&p!=NULL) //查找第i-1个节点
{
j++;
p=p->next;
}
if(p==NULL) //未找到第i-1个节点
{
return false;
}
else//找到第i-1个节点,插入新节点
{
s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=m;
s->next=p->next;//将原p指向的下一个节点改为s指向该节点
p->next=s;//将原p指向的下一个节点指为s
return true;
}
}
bool ListDelete(LinkNode *&L,int i,ElemType &e) //删除第i个元素
{
int j=0;
LinkNode *p=L,*q;
if(i<=0)return false;
while(j<i-1&&p!=NULL)//查找第i-1个节点
{
j++;
p=p->next;
}
if(p==NULL)
{
return false;
}
else //找到第i-1个节点
{
q=p->next; //q指向第i个节点
if(q==NULL)
{
return false;//若第i个节点不存在
}
e=q->data;
p->next=q->next;
free(q);//释放q节点
return true;
}
}
int main()
{
LinkNode *h;
ElemType e;
printf("单链表的基本运算如下:\n");
printf(" (1)初始化单链表h\n"); InitList(h);
printf(" (2)依次采用尾插法插入a,b,c,d,e元素\n");
ListInsert(h,1,'a');
ListInsert(h,2,'b');
ListInsert(h,3,'c');
ListInsert(h,4,'d');
ListInsert(h,5,'e');
printf(" (3)输出单链表h: ");DispList(h);
printf(" (4)单链表的长度:%d\n",ListLength(h));
printf(" (5)单链表h为%s\n",(ListEmpty(h)?"空":"非空"));
GetElem(h,3,e);//得到第三个元素的位置
printf(" (6)单链表h的第三个元素:%c\n",e);
printf(" (7)元素a的位置:%d\n",LocateElem(h,'a'));
printf(" (8)在4个元素位置插上f元素\n");ListInsert(h,4,'f');
printf(" (9)输出单链表h: ");DispList(h);
printf(" (10)删除h的第3个元素\n");ListDelete(h,3,e);
printf(" (11)输出单链表h: ");DispList(h);
printf(" (12)释放单链表h\n");DestoryList(h);
return 1;

}

 

 


/*
*& 指针引用
为的是在函数中可以修改指针的指向...
C++方面知识
指针是一个存放地址的变量,指针引用指的是这个存放地址的变量的引用。
所以如果有需求想改变指针所指的对象即想要改变指针变量里存放的地址,就要使用指针引用。
*/

posted @ 2020-11-27 18:32  txzing  阅读(388)  评论(0编辑  收藏  举报