链表算法1

#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头结点,组成完成循环链表
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值