1. 完成单链表的如下设计:
抽象方法包括:
单链表的整表创建。
单链表的第i个位置插入元素。
单链表的第i个位置删除元素。
单链表的按值查询。
单链表的整表输出。
单链表的整表删除。
主函数中需要调用以上方法以演示运行结果。
代码实现:
#include<stdlib.h>
#include<stdio.h>
#define OK 1
#define ERROR -1
#define MAX_SIZE 100
typedef int ElemType;
typedef int Ststus;
//1.链表的构建
typedef struct Lnode
{
ElemType data;//数据域,保存节点值
struct Lnode *next;//指针域
}LNode;//节点类型
LNode *create_LinkList()
{
int data;
LNode *p,*q,*head;
head=p=(LNode*)malloc(sizeof(LNode));//创建头文件
head->next=NULL;//头文件指针域为空
printf("请输入数字(空格间隔),终止输入请按999\n");
while(1)
{
scanf("%d",&data);//循环取值
if(data==999)//设定999为结束符号
{
printf("已停止输入\n");
break;//取值结束跳出循环
}
else
{
q=(LNode*)malloc(sizeof(LNode));//创建新节点
q->next=NULL;//设定新节点指针域为空
}
q->data=data;//向新节点赋值
q->next=p->next;
p->next=q;//尾插法链接节点
p=q;//指针后移
}
return (head);//返回头指针
}
//2.获得第i个节点的数值
ElemType Get_Elem(LNode *L,int i)//返回 ElemType类型的值
{
int j=1;
ElemType m=-256;
LNode *p;
p=L->next;//头指针中数据域无数据
while(p!=NULL && j<i)//循环判断是否为空,并且是否到达指定位置
{
p=p->next;
j++;
}
if(j==i)
return (p->data);//返回相应的值
else
return m;
}
//3.通过数值来查找节点序号
LNode *Locate_Node(LNode *L,int key)
{
LNode *p;
int i=1;
p=L->next;//头指针中数据域无数据
while(p->next!=NULL&&p->data!=key)//判断是否为空,是否找到数值对应节点
{
i++;
p=p->next;
}
if(p->data==key)
{
printf("已找到该数值\n");
printf("是第%d个节点\n",i);//找到节点,输出节点的位置 (序号)
return p;
}
else
{
printf("未找到该数值\n");
return (NULL);
}
}
//4.链表的插入
void Insert_LNode(LNode *L,int loc,ElemType e)
// 在以L为头结点的单链表的第i个位置插入值为e的结点
{
int j=0;
LNode *p=L;
while(p->next!=NULL && j<loc-1)//循环判断是否为空,并且是否到达指定位置
{
p=p->next;
j++;
}
if(j==loc-1)
{
LNode *q=(LNode *)malloc(sizeof(LNode));//构建新的节点
q->data = e;//对新节点赋值
q->next = p->next;//新节点连接上链表
p->next = q;
}
}
//5.删除序号节点
void Delelte_serial(LNode *L,ElemType a)
{
LNode *p,*q;
ElemType i=1;
p=q=L;
while(i!=a)//判断是否找到相应位置
{
q=q->next;
i++;
}
p=q;
q=q->next;
p->next=q->next;//将链表连接上(将q节点跳过,便于释放)
free(q);//释放节点
}
//6.删除重复节点
void Delete_Node_value(LNode *L)
{
LNode *p,*q,*ptr;
p = L->next;
while(p != NULL) // p用于遍历链表
{
q = p;
while(q->next != NULL) // q遍历p后面的结点与p数值比较
{
if(q->next->data == p->data)
{
ptr = q->next; // ptr保存需要删掉的结点
q->next = ptr->next; // 需要删掉的结点的前后结点钩链
free(ptr);//释放掉ptr指向的节点
}
else
q = q->next;//q指向下一个节点
}
p = p->next;//q指向下一个节点
}
}
//7.两个链表的合并
LNode *Merge_LinkList(LNode *p, LNode *q)
{
LNode *La,*Lb,*Lc,*Ld,*ptr;
Ld=ptr=(LNode*)malloc(sizeof(LNode));
ptr->next=NULL;
La=p->next;
Lb=q->next;
while(La!=NULL && Lb!=NULL)
{
Lc=(LNode*)malloc(sizeof(LNode));
Lc->next=NULL;
ptr->next=Lc;
ptr=ptr->next;
if(La->data<Lb->data)
{
Lc->data=La->data;
La=La->next;
}
else if(La->data==Lb->data)
{
Lc->data=La->data;
La=La->next;
Lb=Lb->next;
}
else
{
Lc->data=Lb->data;
Lb=Lb->next;
}
}
if(La==NULL)
while(Lb!=NULL)
{
Lc=(LNode*)malloc(sizeof(LNode));
Lc->next=NULL;
ptr->next=Lc;
ptr=ptr->next;
Lc->data=Lb->data;
Lb=Lb->next;
}
else
while(La!=NULL)
{
Lc=(LNode*)malloc(sizeof(LNode));
Lc->next=NULL;
ptr->next=Lc;
ptr=ptr->next;
Lc->data=La->data;
La=La->next;
}
return Ld;
}
//8.遍历链表仅仅用于检测
void Bianli(LNode *p)
{
p=p->next;
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
printf("OK\n");
}
//9.释放三个链表
LNode * Frees(LNode *p)
{
LNode *q;
while(p!=NULL)
{
q=p->next;//先钩链再释放
free(p);
p=q;
}
printf("OK\n");
}
//10.循环输出菜单栏,防止清屏后没有指示
void printf0()
{
printf("****************************************************\n");
printf("1.链表的构建\n");
printf("2.通过序号查询节点数值\n");
printf("3.通过序号插入节点数值\n");
printf("4.通过数值查找节点序号\n");
printf("5.删除序号节点\n");
printf("6.删除重复节点\n");
printf("7.第二个链表的构建以及链表的合并 \n");
printf("8.遍历三个链表\n");
printf("9.释放三个链表\n");
printf("0.退出\n");
printf("****************************************************\n");
}
int main()
{
LNode *p,*q,*ptr;
int i,j,a;
printf0();
do
{
printf("\n请输入选择的指令:\n");
scanf("%d",&a);//输入菜单指令
switch(a)
{
case 1:
{//1.链表的构建
p=create_LinkList();
}
break;
case 2:
{//2.通过序号查询节点数值
printf("请输入需要查询的节点:\n");
scanf("%d",&i);
j=Get_Elem(p,i);
printf("第%d个节点的数值为%d\n",i,j);
}
break;
case 3:
{//3.通过序号插入节点数值
printf("请输入需要插入的节点位置以及数值:\n");
scanf("%d",&i);
scanf("%d",&j);
Insert_LNode(p,i,j);
}
break;
case 4:
{//4.通过数值查找节点序号
printf("请输入需要查询的值:\n");
scanf("%d",&i);
q=Locate_Node(p,i);
}
break;
case 5:
{//5.删除序号节点
printf("请输入需要删除节点的序号:\n");
scanf("%d",&i);
Delelte_serial(p,i);
}
break;
case 6:
{//6.删除重复节点
printf("删除重复节点:\n原链表:");
Bianli(p);
Delete_Node_value(p);
printf("已删除重复节点\n链表:");
Bianli(p);
}
break;
case 7:
{//7.第二个链表的构建以及链表的合并
printf("第二个链表构建:\n");
q=create_LinkList();
ptr=Merge_LinkList(p,q);
}
break;
case 8:
{//8.遍历三个链表
printf("第一个链表:\n");
Bianli(p);
printf("第二个链表:\n");
Bianli(q);
printf("第三个链表:\n");
Bianli(ptr);
}
break;
case 9:
{//9.释放三个链表
printf("第一个链表\n");
Frees(p);
printf("第二个链表\n");
Frees(q);
printf("第三个链表\n");
Frees(ptr);
}
break;
case 0:
{
printf("谢谢使用我的程序\n");
}
break;
default:
{
printf("输入错误,请重新输入\n");
system("pause");
}
break;
}
}while(a!=0);
}
结果如下: