#include <stdio.h>
// 定义单链表
typedef struct node
{
ElemType data;
struct node *next;
} LNode,*LinkList
// creat_LinkList from head
LinkList Creat_LinkList1(){
LinkList H=(LinkList)malloc(sizeof(LNode));//生成头结点
H->next = NULL;//空表
LNode *s;
int x;//设置元素的类型为int
scanf('%d',&x);
while(x!= -1){
s=(LinkList)malloc(sizeof(LNode));
s->data = x;
s->next = H->next;
H->next = s;
scanf("%d",&x);
}
return H;
}
LinkList Creat_LinkList2(){
LinkList H=(LinkList)malloc(sizeof(LNode));
H->next = NULL;
LNode *s,*r=H;
int x;
scanf("%d",&x);
while(x!= -1){
s=(LInkList)malloc(sizeof(LNode));
s->data = x;
s->next= r->next;
r->next = s;
r=s;
scanf("%d",&x);
}
return H;
}
int Length_LinkList (LinkList H){
LNode *p = H;
int j=0;
while(p->next != NULL){
p=p->next;
j++
};
return j;
}
// 按照位置查找
LinkList Get_LinkList (LinkList H, int k){
LNode *p=H;
int j=0;
while(p->next != NULL && j<k){
p=p->next;
j++
};
if(j == k) return p;
else return NULL;
}
// 按值查找
LNode *Locate(LinkList H,DataType x){
LNode *p = H->next;
while(p !=NULL && p->data != x)
p=p->next;
return p;
}
//跟上边一样 返回地址的算法
Lnode* LocateElem_L(LinkList L, ElemType e)
{
p = L->next; //指向首元结点的指针p
while (p&&p->data != e)
{
p = p->next; //指向下一个结点
}
return p; //返回当前结点的地址
}
//返回位置的算法
int LocateElem_L(LinkList L, ElemType e)
{
p = L->next; //指向首元结点的指针p
j = 1;
while (p&&p->data != e)
{
p = p->next; //指向下一个结点
j++;
}
if (p)
return j; //返回元素的位置序号
else
return 0;
}
// 插入操作
// 设p指向单链表中的某结点,s指向待插入的新结点,将*s 插入到*p 的后面,
// 操作顺序如下 1 s->next = p->next; p->next = s;
/**
* 如果将新结点插入*s插入到*p前面,其过程分析如下
* 1.首先找到*p的前驱结点*q,
* 2.然后将*s插入到*q之后。
* 设单链表头指针为H
* q=H;
* while(q->next != p)
* q= q->next;
* s->next = q->next;
* q->next = s;//插入
*/
/**
* 将新结点*s插入到第i个结点的位置上,即插入到ai-1 与ai之间
* 算法思路
* 1.查找第i-1个结点,若存在继续(2),否则结束
* 2.创建新结点;
* 3.将新结点插入,结束
*/
int Insert_LinkList (LinkList H,int i,ElemType x)
//在单链表H的第i位置上插入值为x的元素
{
LNode *p,*s;
p=Get_LinkList(H,i-1);//查找第i-1个结点
if(p ==NULL){
printf('插入位置i错');
return ERROR;
}
else{
s=(LinkList)malloc?(sizeof(LNode));//申请新结点
s->data = x;
s->next = p->next;//新结点插入在第i-1个结点后面
p->next = s;
return TRUE;
}
}
//删除操作
/**
* 设p指向单链表中要删除的结点,首先要找到*p的前驱结点*q,
* 然后完成删除操作,操作过程如下
* 1.q->next = p->next;
* 2.free(p);
*
* 删除链表中第i个结点
* 算法思路如下:
* 1.查找第i-1个结点,若存在,则继续(2),否则结束;
* 2.若存在第i个结点则继续3,否则结束;
* 3.删除第i个结点,结束。
*
*/
int Del_LinkList(LinkList H,int i){
LinkList p,q;
p=Get_LinkList(H,i-1);
if(p== NULL){
printf("第i-1个结点不存在");
return ERROR;
}else{
if(p->next == NULL){
printf("第i-1个结点不存在");
return ERROR;
}else{
q=p->next;//指向第i个结点
p->next = q->next;//从链表中删除
free(q);//释放*q
return TRUE;
}
}
}
//典型算法
/**
* 倒置单链表
* 思路:依次取原链表中的每个结点,将其作为第一个结点插入到新链表中,
* 指针p用来指向当前结点,p为空时结束
*/
void Reverse(LinkList H){
LNode *p,*q;
p=H->next;//p指向第一个数据结点
H->next = NULL;//将原链表置为空表H
while(p){
q=p;
p=p->next;
q->next = H->next;//将当前结点插入到头结点的后面
H->next = q;
}
}
/**
* 删除重复结点 时间复杂度为O(n²)
* 思路:用指针p指向第一个结点,从它的直接后继结点开始找与其值相同的结点,
* 找到后将该结点删除;p再指向下一个,以此类推,p指向最后结点时算法结束。
*/
void pur_LinkList (LinkList H){
LNode *p,*q,*r;
p=H->next;//p指向第一个数据结点
if(p!=NULL)
while(p->next){
q=p;
while(q->next){ //从*p的后继开始找重复结点
if(q->next->data == p->data){
r=q->next;//找到重复结点,用r指向,删除*r
q->next = r->next;
free(r);
}else q= q->next;
}
p=p->next;//p指向下一个结点,继续
}
}
/**
* 求两个集合的差 若以单链表表示集合,假设集合A用单链表LA表示
* ,集合B为LB,求两集合的差A-B
* 思路:若以单链表表示集合,假设集合A用单链表LA表示,集合B为LB,求两集合的差A-B
* 找到后将该结点删除;p再指向下一个,以此类推,p指向最后结点时算法结束。
*/
void Difference (LinkList LA,LinkList LB){//此算法求两个集合差集
Node *pre,*p,*r;
pre = LA;
p=LA->next;//p指向LA中的某一结点,pre始终指向p的前驱
while(p != NULL){
q=LB->next;//扫描LB中的结点,寻找与LA中*p结点相同的结点
while(q!= NULL && q->data != p->data){
q = q->next;
}
if(q != NULL){
r = p;
pre->next = p->next;
p = p->next;
free(r);
}else{
pre = p;
p = p->next;
}
}
}
/**
* @brief gdr 单循环链表 op-31 np-43
* 在单链表的基础上,将其最后一个站点的指针指向该链表头结点,使得链表头尾结点相连
* 就构成了单循环链表(Circular Linked List)
* 尾指针即最后一个元素为rear a1 位置为rear->next->next an位置rear 数据域rear->data
* 典型合并操作 2单循环链表合并
* p=RA->next; //保存RA的头结点指针
* RA->next = RB->next->next;//头尾相接
* free(RB->next) //释放RB的头结点
* RB->next = p; //指向RA头结点,组成完成循环链表
*/
链表算法1
于 2021-05-06 14:06:49 首次发布