前面是基本操作,后面是附加题
main.cpp
#include <iostream>
#include "SList.h"
using namespace std;
int main()
{
LinkList mylist;
InitLinkList(&mylist);
ElemType Item;
LNode *p;
int pos;
int select =1;
while(select)
{
printf("********************单链表基本操作**************************\n");
printf("**[1]前端插入元素************************[2]后端插入元素****\n");
printf("**[3]显示数据元素************************[4]后端删除元素****\n");
printf("**[5]前端删除元素************************[6]显示链表长度****\n");
printf("**[7]按位置插入元素**********************[8]按值删除元素**\n");
printf("**[9]排序********************************[10]逆置链表*******\n");
printf("**[11]查找元素所在位置*******************[12]清空链表*******\n");
printf("**[13]查找链表中大于x的元素个数**********[14]***************\n");
printf("请选择:>>\n");
scanf("%d",&select);
if(select ==0)
break;
switch(select)
{
case 1:
printf("输入元素的值,以-1为结束标志。\n");
while(scanf("%d",&Item),Item!=-1)
{
push_front(&mylist,Item);
}
break;
case 2:
printf("输入元素的值,以-1为结束标志。\n");
while(scanf("%d",&Item),Item!=-1)
{
push_back(&mylist,Item);
}
break;
case 3:
showList(&mylist);
break;
case 4:
pop_back(&mylist);
break;
case 5:
pop_front(&mylist);
break;
case 6:
printf("链表长度为:%d\n",length_list(&mylist));
break;
case 7:
printf("请输入要插入元素的值:\n");
scanf("%d",&Item);
printf("请输入要插入元素的位置:\n");
scanf("%d",&pos);
insertLinklist_pos(&mylist,pos,Item);
break;
case 8:
printf("请输入要删除元素的值:\n");
scanf("%d",&Item);
delete_LinkList_val(&mylist,Item);
break;
case 9:
sortLinkList(&mylist);
break;
case 10:
reverseLinkList(&mylist);
break;
case 11:
printf("请输入要查找元素的值:\n");
scanf("%d",&Item);
pos=findval_val(&mylist,Item);
if(pos==-1)
printf("没有该元素!\n");
else
printf("%d的位置为:%d\n",Item,pos);
break;
case 12:
clearLinkList(&mylist);
break;
case 13:
printf("请输入x的值:\n");
scanf("%d",&Item);
printf("链表中大于%d的元素个数为:%d\n",Item,countX(&mylist,Item));
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
}
destroyLinkList(&mylist); //销毁链表
return 0;
}
SList.h
#ifndef SLIST_H_INCLUDED
#define SLIST_H_INCLUDED
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
typedef int ElemType; //定义类型
typedef struct LNode //定义结点
{
ElemType data; //数据域
struct LNode *next; //指向后继结点的指针域
}LNode,*PNode; //PNode为节点类型指针
typedef struct LinkList //定义链表
{
PNode first; //头指针
PNode last; //尾指针
int list_size; //链表中有效元素个数
}LinkList;
int countX(LinkList *list,ElemType x); 统计大于某个值的节点个数//
/基本操作/
void InitLinkList(LinkList *list);//初始化链表
LNode *_buyNode(ElemType Item);//新增结点
void push_front(LinkList *list,ElemType x);//向链表中头插结点
void push_back(LinkList *list,ElemType x);//向链表中尾插结点
void showList(LinkList *list);//显示链表元素
void pop_back(LinkList *list);//尾部删除结点
void pop_front(LinkList *list);//头部删除节点
int length_list(LinkList *list);//返回链表长度
void insertLinklist_pos(LinkList *list,int pos,ElemType key);//按照pos指定的位置插入元素
void delete_LinkList_val(LinkList *list,ElemType x);//删除第一个值为x的元素
void sortLinkList(LinkList *list); //排序
void reverseLinkList(LinkList *list);//逆置链表元素
void clearLinkList(LinkList *list);//清空单链表
void destroyLinkList(LinkList *list);//销毁单链表
int findval_val(LinkList *list,ElemType key);//查找链表中首个值为key的元素位置
#endif // SLIST_H_INCLUDED
SList.cpp
#include "SList.h"
int countX(LinkList *list,ElemType x) 统计大于某个值的节点个数//
{
LNode *p=list->first->next;
int n=0;
while(p!=NULL)
{
if(p->data>x)
n++;
p=p->next;
}
return n;
}
void InitLinkList(LinkList *list) //初始化链表
{
LNode *head=(LNode *)malloc(sizeof(LNode));//定义头节点
assert(head!=NULL); //断言空间是否分配成功
head->next=NULL; //将头节点指针域设置为空
list->first=list->last=head; //初始化链表中的头指针、尾指针
list->list_size=0;//初始化链表的长度
}
LNode *_buyNode(ElemType x)//新增结点,注意:返回的是新增节点的指针
{
LNode *s;
s=(LNode *)malloc(sizeof(LNode));
assert(s!=NULL);
s->data=x;
s->next=NULL;
return s;
}
void push_front(LinkList *list,ElemType x) //向链表中头插结点
{
LNode *s;
s=(LNode *)malloc(sizeof(LNode));
assert(s!=NULL);
s->data=x;
//s->next=NULL;
if(list->list_size==0)//注意:若插入元素为第一个元素。则需要修改尾指针指向的位置
{
list->last=s;
}
s->next=list->first->next;
list->first->next=s;
list->list_size++;//链表长度加1
}
void push_back(LinkList *list,ElemType x) //向链表中尾插结点
{
LNode *s;
s=_buyNode(x);
list->last->next=s;
list->last=s;
list->list_size++;
}
void showList(LinkList *list) //显示链表元素
{
LNode *p;
p=list->first->next;
while(p!=NULL)
{
printf("%d->",p->data);
p=p->next;
}
printf("Nul.\n");
}
void pop_back(LinkList *list) //尾部删除结点
{
//判断是否是空表
if(list->list_size==0)
return;
LNode *p=list->first;
while(p->next!=list->last)//找到倒数第二个结点
{
p=p->next;
}
//删除最后一个结点,并重新定位尾指针
free(list->last);
p->next=NULL;
list->last=p;
list->list_size--;//表的长度减一
}
void pop_front(LinkList *list) //头部删除节点
{
if(list->list_size==0)//判断表是否为空
return;
LNode *p=list->first->next;
list->first->next=p->next;//断开第一个结点的指针
if(p->next==NULL) 如果只有一个元素,需修改尾指针p为最后一个元素
{
list->last=list->first;
}
free(p);
list->list_size--;
}
int length_list(LinkList *list) //返回链表长度
{
return list->list_size;
}
void insertLinklist_pos(LinkList *list,int pos,ElemType key)//按照pos指定的位置插入元素
{
if(pos<1 || pos>list->list_size+1)
{
printf("输入位置不合理。\n");
return;
}
LNode *s=_buyNode(key);
LNode *p=list->first;
for(int i=1;i<pos;i++)//将p定位到要插入位置的前一个结点
{
p=p->next;
}
s->next=p->next;
p->next=s;
list->list_size++;
}
void delete_LinkList_val(LinkList *list,ElemType x)//删除第一个值为x的元素
{
if(list->list_size==0)
return;
LNode *p=list->first;
//将p定位到要删除节点的前一个结点
while(p->next!=NULL && p->next->data!=x )//注意p!=NULL必须在前面
{
p=p->next;
}
if(p->next==NULL)//没找到
{
printf("表中没有值为%d的元素。\n",x);
return;
}
else if(p->next==list->last)//如果要删除的节点为最后一个节点
pop_back(list);
else//找到后,删除p后面的节点
{
LNode *q=p->next;
p->next=q->next;
free(q);
}
list->list_size--;
}
void sortLinkList(LinkList *list) //排序
{
if(list->list_size==0)
return;
LNode *p,*q,*s;
//首元素结点之后断开
p=list->first->next;
q=p->next;//q记录断开后的节点地址
p->next=NULL;
list->last=p;//重新定为尾指针
while(q!=NULL) //依次扫描剩余结点
{
p=q;
q=q->next;//重新定位p、q的位置,p指向剩余结点中每轮要插入的结点。q执行p的下一个节点
s=list->first;//s指向待排序链表的头节点
while(s->next!=NULL && s->next->data<p->data)
{
//如果s所指的下一个结点小于要插入的p所指结点,则s向后移动
s=s->next;
}
//跳出循环后,s所指的下一个结点值大于p所指节点,则将p插在s之后
if(s->next==NULL)//注意:如果插入的位置为最后一个节点,则修改尾指针位置
{
list->last=p;
}
//将p插在s之后
p->next=s->next;
s->next=p;
}
}
void reverseLinkList(LinkList *list)//逆置链表元素
{
if(list->list_size==0 || list->list_size==1)
return;
//将链表从第一个结点后断开,然后将其余节点前插
LNode *p,*q,*s;
p=list->first->next;
q=p->next;
list->last=p;
p->next=NULL;
//将剩余结点前端插入链表
while(q!=NULL)
{
p=q;
q=q->next;
s=list->first;
p->next=s->next;
s->next=p;
}
}
int findval_val(LinkList *list,ElemType key)//查找链表中首个值为key的元素位置
{
int i=1;
if(list->list_size==0)
{
return -1;
}
LNode *p=list->first->next;
while(p!=NULL && p->data!=key)
{
p=p->next;
i++;
}
if(p==NULL)
return -1;
else
return i;
}
void clearLinkList(LinkList *list)//清空单链表
{
if(list->list_size==0)
return;
LNode *p=list->first->next;
while(p!=NULL)
{
list->first->next=p->next;
free(p);
p=list->first->next;
}
list->last=list->first;
list->list_size=0;
}
void destroyLinkList(LinkList *list)//销毁单链表
{
clearLinkList(list);
free(list->first);
list->first=list->last=NULL;
list->list_size=0;
}
还有两个附加题
**(1)**拆分l1,l1存奇数位置元素,l2存偶数位置元素
**(2)**将有序的l1、l2合并为l3后仍有序
可以在前文基础上增加,或者像这样再来一个项目,尝试再建一个项目时,某些前文的type也是需要的,必要的:初始化函数void InitLinkList(LinkList *list);还有插入,排序和显示。
main.cpp
#include <iostream>
#include "SList.h"
using namespace std;
int main()
{
ElemType item;
LinkList L1,L2;
InitLinkList(&L1);
InitLinkList(&L2);
printf("输入L1元素,以-1为结束标志:\n");
while(scanf("%d",&item),item!=-1)
{
push_back(&L1,item);
}
printf("输入L2元素,以-1为结束标志:\n");
while(scanf("%d",&item),item!=-1)
{
push_back(&L2,item);
}
//Depatch(&L1,&L2);
//showList(&L1);
//showList(&L2);
LinkList L3;
InitLinkList(&L3);
Depatch(&L1,&L2);
printf("拆分后链表:");
showList(&L1);
showList(&L2);
mergerL(&L1,&L2,&L3);
printf("合并后链表:");showList(&L3);
return 0;
}
SList.h
#ifndef SLIST_H_INCLUDED
#define SLIST_H_INCLUDED
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
typedef int ElemType; //定义类型
typedef struct LNode //定义结点
{
ElemType data; //数据域
struct LNode *next; //指向后继结点的指针域
}LNode,*PNode; //PNode为节点类型指针
typedef struct LinkList //定义链表
{
PNode first; //头指针
PNode last; //尾指针
int list_size; //链表中有效元素个数
}LinkList;
void InitLinkList(LinkList *list);//初始化链表
void showList(LinkList *list);//显示链表元素
void sortLinkList(LinkList *list); //排序
void push_back(LinkList *list,ElemType x);//向链表中尾插结点
/单链表的拆分//
void Depatch(LinkList *l1,LinkList *l2);//拆分l1,l1存奇数位置元素,l2存偶数位置元素
/单链表的合并//
void mergerL(LinkList *l1,LinkList *l2,LinkList *l3);//将有序的l1、l2合并为l3后仍有序
#endif // SLIST_H_INCLUDED
SLink.cpp
#include "SList.h"
void InitLinkList(LinkList *list) //初始化链表
{
LNode *head=(LNode *)malloc(sizeof(LNode));//定义头节点
assert(head!=NULL); //断言空间是否分配成功
head->next=NULL; //将头节点指针域设置为空
list->first=list->last=head; //初始化链表中的头指针、尾指针
list->list_size=0;//初始化链表的长度
}
LNode *_buyNode(ElemType x)//新增结点,注意:返回的是新增节点的指针
{
LNode *s;
s=(LNode *)malloc(sizeof(LNode));
assert(s!=NULL);
s->data=x;
s->next=NULL;
return s;
}
void push_back(LinkList *list,ElemType x) //向链表中尾插结点
{
LNode *s;
s=_buyNode(x);
list->last->next=s;
list->last=s;
list->list_size++;
}
void showList(LinkList *list) //显示链表元素
{
LNode *p;
p=list->first->next;
while(p!=NULL)
{
printf("%d->",p->data);
p=p->next;
}
printf("Nul.\n");
}
void sortLinkList(LinkList *list) //排序
{
if(list->list_size==0)
return;
LNode *p,*q,*s;
//首元素结点之后断开
p=list->first->next;
q=p->next;//q记录断开后的节点地址
p->next=NULL;
list->last=p;//重新定为尾指针
while(q!=NULL) //依次扫描剩余结点
{
p=q;
q=q->next;//重新定位p、q的位置,p指向剩余结点中每轮要插入的结点。q执行p的下一个节点
s=list->first;//s指向待排序链表的头节点
while(s->next!=NULL && s->next->data<p->data)
{
//如果s所指的下一个结点小于要插入的p所指结点,则s向后移动
s=s->next;
}
//跳出循环后,s所指的下一个结点值大于p所指节点,则将p插在s之后
if(s->next==NULL)//注意:如果插入的位置为最后一个节点,则修改尾指针位置
{
list->last=p;
}
//将p插在s之后
p->next=s->next;
s->next=p;
}
}
/单链表的合并//
void mergerL(LinkList *L1,LinkList *L2,LinkList *L3) //将有序的l1、l2合并为l3后仍有序
{
sortLinkList(L1);
sortLinkList(L2);
LNode *La,*Lb,*Lc;
La=L1->first->next;
Lb=L2->first->next;
Lc=L3->first;
while(La!=NULL && Lb!=NULL)
{
if(La->data<Lb->data)
{
Lc->next=La;
Lc=Lc->next;
La=La->next;
}
else
{
Lc->next=Lb;
Lc=Lc->next;
Lb=Lb->next;
}
}
if(La!=NULL)
{
Lc->next=La;
L3->last=L1->last;
}
if(Lb!=NULL)
{
Lc->next=Lb;
L3->last=L2->last;
}
L3->list_size=L1->list_size+L2->list_size;
}
void Depatch(LinkList *L1,LinkList *L2)//拆分l1,l1存奇数位置元素,l2存偶数位置元素
{
LNode *p,*q,*s;
p=L1->first->next;
L1->last=p;
while(p!=NULL)
{
q=p->next;
s=q->next;
//将奇数位结点后端插入l1
p->next=NULL;
L1->last->next=p;
L1->last=p;
//将偶数位结点前端插入l2
q->next=L2->first->next;
L2->first->next=q;
L2->last=q;
p=s;//重新定位p
}
}