/*
Project: single linkeed list (数据结构 单链表)
Date: 2021-10-7 09:26:57
Author: Frank Wang
InitList(LinkList &L) 参数:单链表L 功能:初始化 时间复杂度 O(1)
ListLength(LinkList L) 参数:单链表L 功能:获得单链表长度 时间复杂度O(n)
ListInsert(LinkList &L,int i,ElemType e)
ListDelete(LinkList &L,int i) 参数:单链表L,位置i 功能:删除位置i元素 时间复杂度O(n)[加入了查找]
若已知p指针指向的删除 最好是O(1),因为可以与后继结点交换数据域,然后删除后继结点。
最坏是O(n),即从头查找p之前的结点,然后删除p所指结点
LocateElem(LinkList L,ElemType e) 参数:单链表L,元素e 功能:查找第一个等于e的元素,返回指针 时间复杂度O(n)
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
#define Status int
#define ElemType int
//单链表结点数据结构
typedef struct Node
{
ElemType data;//数据域
struct Node *next;//指针域
}LNode,*LinkList;
//**************************基本操作函数***************************//
//初始化函数
Status InitList(LinkList &L)
{
L = new LNode;//生成头结点 这样删除等操作就不必分第一个结点和其他了
L->next = NULL;
return 1;
}
//获取单链表长度 头结点无数据,不算
int ListLength(LinkList L)
{
LinkList p=L;int sum=0;
while(p)
{
sum++;
p=p->next;
}
return sum-1;//去除头结点
}
//哪种插入法????后插
bool ListInsert(LinkList &L,int i,ElemType e)
{
LNode* s;LinkList p=L;int j=0;
while(p&&(j<i-1))//j指到i-1位置或者p已经到最后时跳出
{
p=p->next;
++j;
}
if(!p||j>i-1)//i<1或者i>ListLength(L)+1时,插入位置无效 不调用ListLength,提高效率
{
printf("插入位置无效!!!\n");
return false;
}
s=new LNode;
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
//删除函数 删除位置i的结点 即删除i-1之后的结点
bool ListDelete(LinkList &L,int i)
{
LNode* s;LinkList p=L;int j=0;
LinkList q;
while(p&&(j<i-1))//j指到i-1位置
{
p=p->next;
++j;
}
if(!(p->next)||j>i-1)//i<1或者i>ListLength(L)时,删除位置无效
{
printf("删除位置无效!!!\n");
return false;
}
q=p->next;
p->next=q->next;
free(q);//释放空间
return true;
}
//查找函数 按值查找 查找第一个等于e的结点 成功返回该结点指针,否则返回NULL
LNode *LocateElem(LinkList L,ElemType e)
{
LNode *p=L;
while(p&&(p->data!=e))
{
p=p->next;
}
return p;
}
//**************************功能实现函数**************************//
void PrintList(LinkList L);
bool insert2(LinkList &L,int i,ElemType e)
{
LNode* s;LinkList p = L , last;int j=0;
while(p&&(j<i))//j指到i位置或者p已经到最后时跳出
{
last = p;
p = p -> next;
++ j;
}
//出来的时候j = i,或者已经走到最后了
if(!p && j == i - 1) //走到最后,并且在i - 1位置
{
s = new LNode;
s -> data = e;
s -> next = p -> next;
p -> next = s;
return true;
}
if (!p && j != i)
{
printf("插入位置无效!!!\n");
return false;
}
s = new LNode;
last -> next = s;
s -> data = e;
s -> next = p;
}
void sort(LinkList &L)//链表选择排序
{
struct Node *p; //=(struct Node*)malloc(sizeof(struct Node));
struct Node *q; //=(struct Node*)malloc(sizeof(struct Node));
ElemType t;
for(p=L->next; p!=NULL ; p=p->next)//选定的位置,从第一个位置开始
{
for(q=p->next;q!=NULL;q=q->next)//每次遍历一遍链表,只要比选定位置的数据小就交换
{
if(q->data<p->data)
{
t=q->data;
q->data=p->data;
p->data=t;
}
}
}
PrintList(L);
}
//遍历输出函数
void PrintList(LinkList L)
{
LinkList p=L->next;//跳过头结点
if(ListLength(L))
{
printf("当前单链表所有元素:");
while(p)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
else
{
printf("当前单链表已空!\n");
}
}
//插入功能函数 调用ListInsert插入
void Insert(LinkList &L)
{
int place;ElemType e;bool flag;
printf("请输入要插入的位置(从1开始)及元素:\n");
scanf("%d%d",&place,&e);
flag=ListInsert(L,place,e);
if(flag)
{
printf("插入成功!!!\n");
PrintList(L);
}
}
void Insert2(LinkList &L)
{
int place;ElemType e;bool flag;
printf("请输入要插入的位置(从1开始)及元素:\n");
scanf("%d%d",&place,&e);
flag=insert2(L,place,e);
if(flag)
{
printf("插入成功!!!\n");
PrintList(L);
}
}
//删除功能函数 调用ListDelete删除
void Delete(LinkList L)
{
int place;bool flag;
printf("请输入要删除的位置(从1开始):\n");
scanf("%d",&place);
flag=ListDelete(L,place);
if(flag)
{
printf("删除成功!!!\n");
PrintList(L);
}
}
//查找功能函数 调用LocateElem查找
void Search(LinkList L)
{
ElemType e;LNode *q;
printf("请输入要查找的值:\n");
scanf("%d",&e);
q=LocateElem(L,e);
if(q)
{
printf("找到该元素!\n");
}
else
printf("未找到该元素!\n");
}
//菜单
void menu()
{
printf("********1.后插 2.删除*********\n");
printf("********3.查找 4.输出*********\n");
printf("********5.退出 6.前插*********\n");
printf("********7.排序 *********\n");
}
//主函数
int main()
{
LinkList L;int choice;
InitList(L);
while(1)
{
menu();
printf("请输入菜单序号:\n");
scanf("%d",&choice);
if(choice==5) break;
switch(choice)
{
case 1:Insert(L);break;
case 2:Delete(L);break;
case 3:Search(L);break;
case 4:PrintList(L);break;
case 6:Insert2(L);break;
case 7:sort(L);break;
default:printf("输入错误!!!\n");
}
}
return 0;
}
结构体到单链表的过渡
#include<stdio.h>
#include<stdlib.h>
int num=0;
struct student
{
char name[20];
int score;
};
typedef struct Node
{
struct student data;//数据域
struct Node *next;//指针域
}List;
List *CreateHead()//创造头节点
{
List *headNode=(List *)malloc(sizeof(List));
headNode->next=NULL;
return headNode;
};
List *CreateNode(struct student data)
{
List *newNode=(List *)malloc(sizeof(List));
newNode->data=data;
newNode->next=NULL;
return newNode;
}
void insertNodeByHead(List *headNode,struct student data)//链表的前插
{
List *newNode=CreateNode(data);
newNode->next=headNode->next;
headNode->next=newNode;
num++;
}
void insertNodeByTail(List *headNode,struct student data)//链表的后插
{
List *p=headNode;
List *newNode=CreateNode(data);
while(p->next!=NULL)
{
p=p->next;
}
p->next=newNode;
num++;
}
void del_Node(List *headNode)//删除节点
{
int i,n=0;
List *p=headNode,*ptr;
printf("请输入你要修改的节点位置:");
scanf("%d",&i);
if(i<1||i>num)
{
printf("删除位置错误\n");
return;
}
while(p->next!=NULL)
{
ptr=p;
p=p->next;
n++;
if(n==i)
{
ptr->next=p->next;
break;
}
}
free(p);
num--;
}
void search_Node(List *headNode)//节点位置查询
{
int i,k=0;
List *p=headNode;
printf("请输入你要搜索的位置:");
scanf("%d",&i);
if(i<1||i>num)
{
printf("搜索位置有误\n");
return;
}
else
{
while(p->next!=NULL)
{
p=p->next;
k++;
if(k==i)
{
printf("姓名:%s 分数:%d\n",p->data.name,p->data.score);
printf("搜索完毕");
break;
}
}
}
}
void printfList(List *headNode)//打印链表
{
List *pmove=headNode->next;
printf("name\tscore\n");
while(pmove!=NULL)
{
printf("%s\t%d\n",pmove->data.name,pmove->data.score);
pmove=pmove->next;
}
}
void sort_list(List *headNode)//链表排序
{
int i,j;
struct student temp;
List *L=headNode;
List *p,*ptr;
for(i=0; i<num-1; i++)
{
L=headNode->next;
{
for(j=0; j<num-i-1; j++)
{
p=L;//前缀
ptr=L->next;//后缀
if(p->data.score>ptr->data.score)
{
temp=p->data;
p->data=ptr->data;
ptr->data=temp;
}
L=L->next;
}
}
}
}
void menu(List *headNode)
{
struct student stu;
char choice;
while(1)
{
printf("请输入你想要选择的功能:\n");
printf("1.前插\n");
printf("2.删除\n");
printf("3.查找\n");
printf("4.输出\n");
printf("5.后插\n");
printf("6.排序\n");
printf("7.退出\n");
setbuf(stdin,NULL);
scanf("%c",&choice);
switch(choice)
{
case '1':
printf("请输入姓名和分数");
setbuf(stdin,NULL);
scanf("%s %d",stu.name,&stu.score);
insertNodeByHead(headNode,stu);
break;
case '2':
del_Node(headNode);
break;
case '3':
search_Node(headNode);
break;
case '4':
printfList(headNode);
break;
case '5':
printf("请输入姓名和分数");
setbuf(stdin,NULL);
scanf("%s %d",stu.name,&stu.score);
insertNodeByTail(headNode,stu);
break;
case '6':
sort_list(headNode);
printfList(headNode);
break;
case '7':
exit(0);
default:
printf("请在(1~7之间输入)\n");
return;
}
}
}
int main()
{
List *ListNOde=CreateHead();
while(1)
{
menu(ListNOde);
}
return 0;
}