#include<stdio.h>
#include<stdlib.h>
//先来归纳一下malloc怎么用:目前用过都是对指针-(指针类型)malloc(sizeof(指向对象类型))
/*
顺序表-插入删除不方便都要移动、预先静态分配(难以确定规模有溢出风险)
下面介绍单链表
*/
#define ElemType char
//搞清楚概念:头指针,头节点、数据域+指针域、空
//Node *和LinkList同为结构指针类型,不同的是LinkList往往用来强调是头指针变量,而Node *往往被用来定义指向单链表中结点的指针
typedef struct Node
{
ElemType data;
struct Node *next;
} Node, *LinkList;
//单链表判空分为带头结点和不带头节点两种(假设L是头指针,对应判断方式是 L->next==NULL 或 L == NULL)
//基本操作:初始化、建立、查找、求长度、插入、删除
//说实话不太理解为什么要构造一个指向头指针的指针L
//初始化:注释写在前面:第一行建立头结点、第二行初始化链表为空
void InitList(LinkList *L)
{
*L = (LinkList)malloc(sizeof(Node));
(*L)->next=NULL;
}
//建立单链表(头插法、尾插法)
//L是带头结点的空链表头指针(L->next=Null)
void CreateFromHead(LinkList L)
{
Node *s;
char c;
flag = 1;//判断是否终止
while(flag)
{
c=getchar();
if(c!='$')
{
s=(Node *)malloc(sizeof(Node));
s->data=c;
s->next=L->next;
L->next=s;
}
else{
flag=0;
}
}
}
//头插法建表结点次序与输入次序相反
void CreateFromTail(LinkList L){
Node *s, *r;//r是表尾指针
r=L;
char c;
int flag;
while(flag)
{
c=getchar();
if(c!='$')
{
s->data=c;
r->next=s;
r=s;
}
else{
flag=0;
r->next=NULL;//不同于头插法,这里需要自己设置为空(尾插法破坏了一开始的NULL)
}
}
}
//查找:按序号查找和按元素查找
//按序号在带头结点的单链表中查找第i个结点,返回指向改结点的指针
Node *Get(LinkList L, int i)
{
if(i<=0) return NULL;
int j=0;//计数器
Node *p;//记忆当前指针
p=L->next;//觉得这里改成这样:因为头结点实际上是第0个结点
//终止条件:如果p为NULL即为p是单链表尾指针的指针域
while((p!=NULL)&&(j<i)){
p=p->next;
j++;
}
if(i==j) return p;
else return NULL;//找不到(i超出链表长度)
}
//按值查找
Node *Locate(LinkList L, ElemType key)
{
Node *p;
p=L->next;
//终止条件: p!=NULL;这恰好保证了如果没有对应元素key我们返回p会是NULL
while(p->next!=NULL){
if(p->data!=Key)
p=p->next;
else
break;
}
return p;
}
//求单链表长度操作
int ListLength(LinkList L)
{
Node *p;
p=L->next;//p是头结点的指针域,指向真正的链表首结点
int j=0;
while(p!=NULL)
{
j++;
p=p->next;
}
return j;
}
#define ERROR 0
#define OK 1
//用pre指示第(i-1)个结点
//单链表插入
//插入共有n+1个位置(头结点一直到尾结点后),对应i的取值可以是1到n+1
int InsList(LinkList L, int i, ElemType e)
{
//第一步是从头结点开始查找第(i-1)个结点,实际上头结点就是我们的第0个结点
//pre是指向第i-1个结点的指针,指向头结点的指针就是L
//最坏的情况就是pre到了NULL即尾结点的指针域还没有找到第(i-1)个结点 ,这说明i越界了
Node *pre, *s;
pre=L;
int j=0;
if(i<=0) return ERROR;
while((pre!=NULL)&&(j<i-1))
{
j++;
pre=pre->next;
}
if(pre==NULL){
printf("插入位置不合理!\n");
return ERROR;
}
else
{
s=(Node *)malloc(sizeof(Node));//由于s未初始化实际上是个野指针,所以我们需要给他分配一定空间
s->data=e;
s->next=pre->next;
pre->next=s;
return OK;
}
}
//单链表删除
//不同于插入位置有n+1个,实际上删除能够合法的位置也就n个
//pre是指向第i-1个结点的指针,这里的i取值是1到n。pre->next为空说明它对应的结点是尾结点,而这是不合法的。
int DelList(LinkList L, int i, ElemType *e)
{
if(i<=0)
{
return ERROR;
}
Node *pre, *s;
int j=0;
//第一步是一样的,查找第(i-1)结点
while((pre->next!=NULL)&&(j<i-1))
{
pre=pre->next;
j++;
}
if(pre->next==NULL){
printf("插入位置不合理!\n");
return ERROR;
}
else{
s=pre->next;//有初始化,不用malloc了
*e=s->data;
pre->next=s->next;
free(s);
return OK;
}
}
//例题1-将有序单链表合并成新的有序单链表
int main()
{
return 0;
}