逻辑结构
单个结点由数据域与一个指针域相结合而成。数据域中的数据类型可以是任意类型,比如说是int,float,double等。指针域中指针指向后继元素,即存放后继元素的物理储存地址。
一个单链表由头结点(其中包含头指针,其中的数据域可以不存放数据),表中结点,尾结点组成。
头指针是单链表与外界的唯一接口,它指向单链表中的第一个结点(其中的数据域中存放数据)。
尾结点中的数据域中存放数据,但是它的指针域为空,即NULL。
物理结构
链式存储,利用一组物理上任意(连续或者不连续)的内存单元储存一组逻辑上存在连续关系的数据。
要查找单链表中的某个数据域中的元素必须先得到该数据域所在结点的前继元素(前继结点的指针域)。
/*定义单链表结点的储存结构*/
typedef struct node
{
int data; //定义结点数据域
struct node *next; //定义结点指针域
}NODE ; //定义该结点数据类型的别名为NODE
/*建立单链表-头插法*/
void GreatList (int len) // len-单链表的表长
{
NODE *h;//定义头结点,即该单链表表名为h
NODE *p;//操作结点
h=(NODE*)malloc(sizeof(NODE));
h->next =NULL;
for (int i=len;i>0;i--)
{
p=(NODE*)malloc(sizeof(NODE));//创造新结点p
cin>>p->data; //输入新结点的数据域内容
p->next =h->next; //新结点指针域存放上步循环中第一个结点的物理存放地址
h->next =p; //头结点首地址重新指向本次循环后产生的新的第一个结点的物理地址
}
}
/*建立单链表-尾插法*/
void CreateList (int len ) // len- 表长
{
NODE *h; , //定义头指针,即该单链表表名为h
NODE *p; //操作结点
NODE *s; //尾结点
h=(NODE*)malloc(sizeof(NODE));//开辟头结点h的储存空间
s=(NODE*)malloc(sizeof(NODE));//开辟尾结点s的储存空间
h->next =s;
cin>>s->data;
s->next =NULL;
for (int i =len ;i>0;--i)
{
p=(NODE*)malloc(sizeof(NODE));//开辟新的结点空间
cin>>p->data;
p->next=NULL; //新结点指针域为空
s->next =p ; //连接新结点的物理储存地址
s=p; //更新尾结点
}
}
/*求表长*/ (时间复杂度为O(n))
int GetLength (NODE *h)
{
int count=0; //计入表的长度
NODE *p;
p=h->next;
while (p!=NULL) //判断是否为空表
{
count++; //每找到一个指针域不为NULL的结点,自加1
p=p->next; //操作结点后移
}
return count; //返回计数结果
}
/*查找第k个结点的数据域值*/(时间复杂度为O(n))
int FindList (NODE *h,int k,int len)
{
NODE *p;
p=h->next;
if (k>len || k<1) //判断取值是否合法
{
return (-1) ;
}
if (k<len && k>=1)
{
for (int i=0;i<k;i++)
{
p=p->next; //操作结点向后移动
}
}
return (p->data) ; //返回该数据域中的值
}
/*输出单链表*/ (时间复杂度为O(n))
void DisplayList (NODE *h)
{
NODE *p;
p=h->next;
while ( p!=NULL) //判断是否为尾结点
{
cout << "第"<<count<<"个数据为:"<<p->data<<endl;
p=p->next; //操作结点向后移动
}
}
/*在第k个位置插入结点*/ (时间复杂度为O(n))
void AddList (NODE *h, int k)
{
NODE *p; //定义操作结点
NODE *new; //定义新结点
new=(NODE*)malloc(sizeof(NODE));
cin>>new->data; // 存入新结点数据
new->next =NULL;
p=h->next;
if (k>len || k<1) //判断取值是否合法
{
return (-1);
}
for (int i=0;i<(k-1);i++)
{
p=p->next; //移动操作结点p
}
new->next =p->next; //新结点的指针域指向后继结点
p->next =new; //前继结点的指针域指向新结点
}
/*删除第k个结点*/(时间复杂度为O(n))
void DeleteList (NODE *h ,int k)
{
NODE *p; //要删除结点前继元素
NODE *d; //要删除的结点
NODE *t; //要删除结点后继元素
p=d=t=h->next;
if ( k>len || k<1) //判断取值是否合法
{
return (-1); `
}
for (int i= 0;i<(k-1);i++)
{
p=p->next; //移动操作结点p
}
for (int i =0;i<k;i++)
{
d=d->next; //移动操作结点 d
}
for (int i=0;i<(k+1);i++)
{
t=t->next; //移动操作结点 t
}
p->next =t;// 将前后继结点相连接
free(d); //将要删除结点的内存释放
}
/*销毁单链表操作 */ (时间复杂度 O(n))
void DistroyList (NODE *h)
{
NODE *p ;
if (h->data =NULL) //排除头结点中数据域为空时的情况
{
p=h;
h=h->next; //头结点后移
free (p);//释放头结点内存空间
}
while ( h->data !=NULL)
{
p=h;
h=h->next; //头结点后移
, free (p); //释放内存空间
}
}
/*逆置单链表*/(时间复杂度O()) (如图3)
void InvertList (NODE *h)
{
NODE *p; //操作结点
NODE *q; //定义保存操作结点指针域中地址的临时结点
p = h->next;
h->next = NULL;//先将头结点指针域置空
while (p!= NULL) //判断是否是原单链表的尾结点
{
q = p->next; //用临时结点来暂时保存操作结点的后继结点地址
p->next = h->next ; //操作结点指针域中地址更新为新产生单链表头结点后面一个后继结点的物理地址
h->next =p; //头结点中指针域中地址更新为操作结点的物理地址
p=q; //将操作结点向后移动
}
}
/*在原本递减有序的单链表中插入数据域为x的结点,保持单链表有序递减*/(时间复杂度O(n))
void AddOrderList (NODE *h)
{
NODE *p; //操作结点
NODE *q; //操作结点的前继结点
NODE *s; //定义新结点
s=(NODE *)malloc(sizeof(NODE));
cin>> s->data;
s->next=NULL; //新结点的指针域置空
p=h->next;
while (p->next != NULL && (s->data)<(p->data))
{
q=p->next; //保存操作结点的前继结点的物理地址
p=p->next; //操作结点后移
}
if (p->next =NULL) //条件(p->next != NULL)不满足 ,x小于单链表中所有数据
{
p->next = s ;
}
else //条件((s->data)<(p->data))不满足,新结点插入在原先头结点与原先尾结点之间
{
s->next =q->next;
q->next=s;
}
}
/*合并a单链表和b单链表,不开辟另外的存储空间*/(时间复杂度为O (n^2))
void CombinList (NODE *a,NODE *b)
{
NODE *r;
NODE *p;
NODE *q;
r = b->next ;
while (r != NULL) //用操作结点r遍历单链表b
{
q = a;
p = a->next;
while ( p != NULL && p->data != r->data) //用操作结点p遍历单链表a ,并附加数值比较循环条件
{
q = p ; //保存删除结点的前继结点
p = p->next;//操作结点p后移
}
if (p != NULL)
{
q->next = p->next; //将删除结点的前继结点与删除结点的后继结点相连接
free (p);//将a中与b中相同的结点删除,内存释放
}
r = r->next; //操作结点r后移
}
r = a ;
while ( r->next != NULL)
{
r = r->next;
}
r->next = b->next ; /'/将单链表b连接在单链表a后面
free (b);//释放单链表b头指针内存空间
}
单个结点由数据域与一个指针域相结合而成。数据域中的数据类型可以是任意类型,比如说是int,float,double等。指针域中指针指向后继元素,即存放后继元素的物理储存地址。
一个单链表由头结点(其中包含头指针,其中的数据域可以不存放数据),表中结点,尾结点组成。
头指针是单链表与外界的唯一接口,它指向单链表中的第一个结点(其中的数据域中存放数据)。
尾结点中的数据域中存放数据,但是它的指针域为空,即NULL。
物理结构
链式存储,利用一组物理上任意(连续或者不连续)的内存单元储存一组逻辑上存在连续关系的数据。
要查找单链表中的某个数据域中的元素必须先得到该数据域所在结点的前继元素(前继结点的指针域)。
/*定义单链表结点的储存结构*/
typedef struct node
{
int data; //定义结点数据域
struct node *next; //定义结点指针域
}NODE ; //定义该结点数据类型的别名为NODE
/*建立单链表-头插法*/
void GreatList (int len) // len-单链表的表长
{
NODE *h;//定义头结点,即该单链表表名为h
NODE *p;//操作结点
h=(NODE*)malloc(sizeof(NODE));
h->next =NULL;
for (int i=len;i>0;i--)
{
p=(NODE*)malloc(sizeof(NODE));//创造新结点p
cin>>p->data; //输入新结点的数据域内容
p->next =h->next; //新结点指针域存放上步循环中第一个结点的物理存放地址
h->next =p; //头结点首地址重新指向本次循环后产生的新的第一个结点的物理地址
}
}
/*建立单链表-尾插法*/
void CreateList (int len ) // len- 表长
{
NODE *h; , //定义头指针,即该单链表表名为h
NODE *p; //操作结点
NODE *s; //尾结点
h=(NODE*)malloc(sizeof(NODE));//开辟头结点h的储存空间
s=(NODE*)malloc(sizeof(NODE));//开辟尾结点s的储存空间
h->next =s;
cin>>s->data;
s->next =NULL;
for (int i =len ;i>0;--i)
{
p=(NODE*)malloc(sizeof(NODE));//开辟新的结点空间
cin>>p->data;
p->next=NULL; //新结点指针域为空
s->next =p ; //连接新结点的物理储存地址
s=p; //更新尾结点
}
}
/*求表长*/ (时间复杂度为O(n))
int GetLength (NODE *h)
{
int count=0; //计入表的长度
NODE *p;
p=h->next;
while (p!=NULL) //判断是否为空表
{
count++; //每找到一个指针域不为NULL的结点,自加1
p=p->next; //操作结点后移
}
return count; //返回计数结果
}
/*查找第k个结点的数据域值*/(时间复杂度为O(n))
int FindList (NODE *h,int k,int len)
{
NODE *p;
p=h->next;
if (k>len || k<1) //判断取值是否合法
{
return (-1) ;
}
if (k<len && k>=1)
{
for (int i=0;i<k;i++)
{
p=p->next; //操作结点向后移动
}
}
return (p->data) ; //返回该数据域中的值
}
/*输出单链表*/ (时间复杂度为O(n))
void DisplayList (NODE *h)
{
NODE *p;
p=h->next;
while ( p!=NULL) //判断是否为尾结点
{
cout << "第"<<count<<"个数据为:"<<p->data<<endl;
p=p->next; //操作结点向后移动
}
}
/*在第k个位置插入结点*/ (时间复杂度为O(n))
void AddList (NODE *h, int k)
{
NODE *p; //定义操作结点
NODE *new; //定义新结点
new=(NODE*)malloc(sizeof(NODE));
cin>>new->data; // 存入新结点数据
new->next =NULL;
p=h->next;
if (k>len || k<1) //判断取值是否合法
{
return (-1);
}
for (int i=0;i<(k-1);i++)
{
p=p->next; //移动操作结点p
}
new->next =p->next; //新结点的指针域指向后继结点
p->next =new; //前继结点的指针域指向新结点
}
/*删除第k个结点*/(时间复杂度为O(n))
void DeleteList (NODE *h ,int k)
{
NODE *p; //要删除结点前继元素
NODE *d; //要删除的结点
NODE *t; //要删除结点后继元素
p=d=t=h->next;
if ( k>len || k<1) //判断取值是否合法
{
return (-1); `
}
for (int i= 0;i<(k-1);i++)
{
p=p->next; //移动操作结点p
}
for (int i =0;i<k;i++)
{
d=d->next; //移动操作结点 d
}
for (int i=0;i<(k+1);i++)
{
t=t->next; //移动操作结点 t
}
p->next =t;// 将前后继结点相连接
free(d); //将要删除结点的内存释放
}
/*销毁单链表操作 */ (时间复杂度 O(n))
void DistroyList (NODE *h)
{
NODE *p ;
if (h->data =NULL) //排除头结点中数据域为空时的情况
{
p=h;
h=h->next; //头结点后移
free (p);//释放头结点内存空间
}
while ( h->data !=NULL)
{
p=h;
h=h->next; //头结点后移
, free (p); //释放内存空间
}
}
/*逆置单链表*/(时间复杂度O()) (如图3)
void InvertList (NODE *h)
{
NODE *p; //操作结点
NODE *q; //定义保存操作结点指针域中地址的临时结点
p = h->next;
h->next = NULL;//先将头结点指针域置空
while (p!= NULL) //判断是否是原单链表的尾结点
{
q = p->next; //用临时结点来暂时保存操作结点的后继结点地址
p->next = h->next ; //操作结点指针域中地址更新为新产生单链表头结点后面一个后继结点的物理地址
h->next =p; //头结点中指针域中地址更新为操作结点的物理地址
p=q; //将操作结点向后移动
}
}
/*在原本递减有序的单链表中插入数据域为x的结点,保持单链表有序递减*/(时间复杂度O(n))
void AddOrderList (NODE *h)
{
NODE *p; //操作结点
NODE *q; //操作结点的前继结点
NODE *s; //定义新结点
s=(NODE *)malloc(sizeof(NODE));
cin>> s->data;
s->next=NULL; //新结点的指针域置空
p=h->next;
while (p->next != NULL && (s->data)<(p->data))
{
q=p->next; //保存操作结点的前继结点的物理地址
p=p->next; //操作结点后移
}
if (p->next =NULL) //条件(p->next != NULL)不满足 ,x小于单链表中所有数据
{
p->next = s ;
}
else //条件((s->data)<(p->data))不满足,新结点插入在原先头结点与原先尾结点之间
{
s->next =q->next;
q->next=s;
}
}
/*合并a单链表和b单链表,不开辟另外的存储空间*/(时间复杂度为O (n^2))
void CombinList (NODE *a,NODE *b)
{
NODE *r;
NODE *p;
NODE *q;
r = b->next ;
while (r != NULL) //用操作结点r遍历单链表b
{
q = a;
p = a->next;
while ( p != NULL && p->data != r->data) //用操作结点p遍历单链表a ,并附加数值比较循环条件
{
q = p ; //保存删除结点的前继结点
p = p->next;//操作结点p后移
}
if (p != NULL)
{
q->next = p->next; //将删除结点的前继结点与删除结点的后继结点相连接
free (p);//将a中与b中相同的结点删除,内存释放
}
r = r->next; //操作结点r后移
}
r = a ;
while ( r->next != NULL)
{
r = r->next;
}
r->next = b->next ; /'/将单链表b连接在单链表a后面
free (b);//释放单链表b头指针内存空间
}