数据结构-线性链表

步入链表啦,链表在查找方面实在麻烦,需要一次次遍历,不过它在插入和删除方面却很从容,只需要改变它的指针域就可实现,和顺序表各有千秋。

1、代码中L始终代表头结点,所以代码中都用其他变量来替代它移动,保证头结点有人保护
2、p->next及p->next->next的遍历的终结位置要注意

看到了个快慢指针的问题,就是在不知链表长度的情况下最快找到中间节点
1、通过遍历整个链表获得长度,在通过长度找到中间结点
2、设置两个指针,一个每次移动两位,一个移动一位
快慢指针应用于:判断单链表是否为循环链表,在有序链表中寻找中位数
http://www.cnblogs.com/hxsyl/p/4395794.html

/**
    *快慢指针
**/
Status FastAndSlowPt(LinkList L, ElemType *e)
{
    LinkList p,s;
    p = L;
    s = L;
    while(p->next != NULL)
    {
        if(p->next->next != NULL)
        {
            p = p->next->next;
            s = s->next;
        }
        else
        {
            p = p->next;
            s = s->next;
        }

    }
    *e = s->data;
    return OK;
}
#include "stdio.h"
#include "stdlib.h"
#include "math.h"

#define MAXSIZE 20
#define OK 1
#define ERROR 0

typedef int Status;
typedef int ElemType;

typedef struct Node
{
    ElemType data;
    struct Node *next;
}Node;
typedef struct Node *LinkList; //定义链表

//输出数据
Status visit(ElemType e)
{
    printf("%d ", e);
    return;
}

//输出整个链表
Status ListTraverse(LinkList L)
{
    LinkList p;
    //切勿写成p=L,这是将p赋值为头结点,而数据从头结点后一个结点开始
    p = L->next;
    while(p)
    {
        visit(p->data);
        p = p->next;
    }
    return OK;
}

/**
    *初始化链表
**/
Status ListInit(LinkList *L)
{
    *L = (LinkList)malloc(sizeof(Node)); //生成头结点
    if(!(*L))   //未分配空间
        return ERROR;
    (*L)->next = NULL; //建立头结点
    return OK;
}

/**
    *链表插入第i个位置数据操作
**/
Status ListInsert(LinkList *L, int i, ElemType e)
{
    int k = 1;
    LinkList p,s;
    p = *L;
    while(p && k<i) //遍历到i-1
    {
        p = p->next;
        k ++;
    }
    if(!p || k>i)//结点i不存在
        return ERROR;
    s = (LinkList)malloc(sizeof(Node));//生成新节点,存储e数据
    s->data = e;
    //一下两句不能颠倒否则会使链表断裂,就是s->next = s;
    s->next = p->next;
    p->next = s;
    return OK;
}

/**
    *链表删除第i个位置数据操作
**/
Status ListDelete(LinkList *L, int i, ElemType *e)
{
    int k=1;
    LinkList p,s;
    p = *L;
    while(p->next && k<i)
    {
        p = p->next;
        k++;
    }
    if(!p || k>i)
        return ERROR;
    s = p->next;
    p->next = p->next->next;
//    p->next = s->next;
    *e = s->data;//将第i位置的数据赋值给*e
    free(s);
    return OK;
}

/**
    *头插法生成链表
**/
Status ListCreHead(LinkList *L, int i)
{
    LinkList p;
    int k;
    *L = (LinkList)malloc(sizeof(Node));
    (*L)->next = NULL;//同链表初始化操作,建立头结点
    for(k=0; k<i; k++)
    {
        p = (LinkList)malloc(sizeof(Node));
        p->data = k+1;
        //同插入结点操作
        p->next = (*L)->next;
        (*L)->next = p;
    }
    return OK;
}

/**
    *尾插法生成链表
**/
Status ListCreTail(LinkList *L, int i)
{
    LinkList p,r;
    int k;
    *L = (LinkList)malloc(sizeof(Node));
    (*L)->next = NULL;//*L要始终指向头结点,作为链表的标志,所以不能移步外地
    r = *L;//r替代L作为移动指针
    for(k=0; k<i; k++)
    {
        p=(LinkList)malloc(sizeof(Node));
        p->data = k+1;
        r->next = p;
        r = p;
    }
    p->next = NULL;
    return OK;
}

/**
    *整表删除
**/
Status ListAllDelete(LinkList *L)
{
    LinkList p, q;
    p = (*L)->next;
    /**
        *从头结点开始删除,若从最后一个结点删除,
        *需要遍历到最后且没指向前一个结点的指针
    **/
    while(p)
    {
        q = p->next;
        free(p);
        p = q;
    }
    (*L)->next = NULL;
    printf("\n删除完毕!");
    return OK;
}

int main(void)
{
    LinkList L, S;
    ElemType e;
    ListCreHead(&L, 6);
    printf("头插法:");
    ListTraverse(L);
//    ListCreTail(&S, 6);
//    printf("\n尾插法:");
//    ListTraverse(S);
//    ListAllDelete(&S);
//    ListInsert(&L, 4, 123);
//    ListTraverse(L);
    printf("\n删除操作后:");
    ListDelete(&L, 4, &e);
    ListTraverse(L);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值