单链表

时间:2017‎年‎1‎月‎25‎日,‏‎21:17:16
自学于郝斌老师


创建链表

PONDE Create_list(void) 
{
    PONDE pHead = (PONDE)malloc(sizeof(NODE));//创建头节点
    PONDE pTail = pHead;//创建尾节点,尾节点等于头节点
    pTail->pNext = NULL;//一定要把尾节点的指针域清空,适用于零个节点的情况
    int len;//len为链表的节点个数
    scanf("%d", &len);
    int val//val为临时保存节点数据域的变量
    for(int i=1;i<=len;i++)
    {
        scanf("%d", &val);
        PONDE pNew = (PONDE)malloc(sizeof(NODE));//创建一个节点,保存新数据
        pNew->data = val;//新节点保存临时数据
        pTail->pNext = pNew;//尾节点指向新节点,第一次循环时也就等于头节点指向下一个节点
        pNew->pNext = NULL;//把新节点的指针域清空
        pTail = pNew;//尾节点等于新节点,pTail时刻指向尾节点
    }
    return pHead;
}
//为什么创建链表的函数是PONDE 类型
// 因为在主函数中的头指针是PONDE类型,创建完链表需要返回pHead。 
//此时,它们俩唯一的要求,就是类型相同才可以接受返回值!

遍历链表


void Traverse_list(PNODE pHead)
{
    PNODE ;//一定要记住什么时候也不要改变头节点的位置。所以用临时一个P代替头节点进行操作
    while (p != NULL)//p = pHead->pNext :p等于头节点之后的第一个节点。
    {                //假设5个节点,循环到第5个节点之后,p = pHead->pNext,这时尾节点的指针域是空的,NULL,循环结束
        printf("%d ", p->data);
        p = p->pNext;//往下循环
    }
    printf("\n");
    return;
}

链表的排序


void Sort_list(PONDE pHead)
{
    PONDE p, q;//这个排序很好诠释了泛型算法。
    int i, j, temp;
    int len = length_list(pHead);
    for (p = pHead->pNext, i = 0;i < len - 1;i++,p=p->pNext)
    {
        for (q = p->pNext,j = i + 1;j < len;j++, q = q->pNext)
        {
            if (p->data < q->data)
            {
                p->data = temp;
                p->data = q->data;
                q->data = temp;
            }


链表的删除节点


bool Delete_list(PONDE pHead, int pos, int *pVal)
{
    int i = 0;
    PONDE p = pHead;//循环结束的节点位置在删除节点位置的前一个
                    //与增加节点不同的是:删除的节点位置不可能是尾节点之后的节点
                    //p->pNext = p->pNext->pNext;第4个节点的指针域等于第5个节点的指针域,也就等于尾指针的指针域,为空
    while (p->pNext != NULL&&i < pos - 1)
    {
        p = p->pNext;
        i++;
    }
    if (i > pos - 1 || p->pNext == NULL)
        return false;
    PONDE q = p->pNext;
    *pVal = q->data;
    p->pNext = p->pNext->pNext;
    free(q);//这两步操作是删除节点的必要操作
    q=NULL:
    return true;
}
//假设有5个节点:1.我要删除第5个节点,必须在第4个节点循环停止,所以循环条件是:p->pNext != NULL
//               2.我要增加第6个节点,我可以一直循环到第5个节点后,所以循环条件是:p != NULL

链表的增加节点


bool Insert_list(PONDE pHead, int pos, int val)
{
    int i = 0;
    PONDE p = pHead;//一定要记住:p = pHead
    while (p != NULL&&i < pos - 1)//p!=NULL,如果有5个节点,增加节点位置是6
                                  //刚刚到循环完第5个节点后结束,因为尾节点的指针域为空
    {                             //要记住:应该循环到增加节点位置的前一个节点结束,我要在第四个节点位置增加节点,应该在第三个节点结束
        i++;
        p = p->pNext;
    }
    if (p == NULL || i > pos - 1)
        return false;
    PONDE pNew = (PONDE)malloc(sizeof(NODE));
    pNew->data = val;
    //第一种增加节点的方式
    PONDE q = p->pNext;
    p->pNext = pNew;
    pNew->pNext = q;
    //第二种增加节点的方式
    pNew->pNext = p->pNext;
    p->pNext = pNew;
}

判断是否空链表


bool Empty_list(PNODE pHead)
{
    if (pHead->pNext == NULL)//如果头节点的指针域为空,意思就是头节点根本没有其他节点的地址,此时链表就为空
        return true;
    else
        return false;
}

求出链表长度


int Length_list(PONDE pHead)
{
    PONDE p = pHead->pNext;//这个没什么好说的
    int len = 0;
    while (p != NULL)
    {
        p = p->pNext;
        len++;
    }
    return len;
}

代码如下:


#include <stdio.h>
#include <stdlib.h>

typedef struct Node
{
    int data;//数据域
    struct Node *pNext;//指针域 
}NODE,*PNODE;//NODE等价于struct NODE  PNODE等价于struct Node *

PNODE create_list(void); 
void traverse_list(PNODE pHead);
bool is_empty(PNODE);
int length_list(PNODE pHead);
bool insert_list(PNODE,int,int);
bool delete_list(PNODE,int,int *);
PNODE sort_list(PNODE);

int main(void)
{
    PNODE pHead = NULL;//等价于 struct Node * pHead = NULL;
    pHead = create_list();//create_list()功能:创建一个非循环单链表,并将该链表的头结点的地址赋给pHead 
    printf("遍历链表输出为:\n");
    traverse_list(pHead);
    int len=length_list(pHead);
    printf("链表的长度是%d",len);
    int flag=1;
    if( is_empty(pHead))
      {
            printf(",并且链表为空。\n");
            flag=0;
      }
    else
    {
             printf(",并且链表不为空.\n");
     }
    if(flag)
    {
    printf("升序后的链表为:\n");
    sort_list(pHead);
    traverse_list(pHead);
    int pos1,val1;
    printf("请输入您要插入节点的位置:\n");
    scanf("%d",&pos1);
    printf("请输入您要插入节点的值:\n");
    scanf("%d",&val1); 
    if(insert_list(pHead,pos1,val1))
    {
        printf("插入成功,您插入的元素是:%d\n",val1);
        printf("插入此节点后的链表为:\n");
        traverse_list(pHead);
    }
    else
    {
        printf("插入失败!您插入的位置不存在!\n");
    }
    int pos2,val2;
    printf("请输入您要删除节点的位置:\n");
    scanf("%d",&pos2);
    if(delete_list(pHead,pos2,&val2))
    {
        printf("删除成功,您删除的元素是:%d\n",val2);
        printf("删除此节点后的链表为:\n");
        traverse_list(pHead);
    }
    else
    {
        printf("删除失败!您删除的元素不存在!\n");
    }
    }
    return 0;
}
PNODE create_list(void)
{
    int len;//用来存放有效节点的个数 
    int i;
    int val;//用来临时存放用户输入的结点的值   
    PNODE pHead =(PNODE)malloc(sizeof(NODE));//分配了一个不存放有效数据的头结点 
    if(pHead==NULL)
    {
        printf("分配失败,程序终止!\n");
        exit(-1);
    }
    PNODE pTail=pHead;
    pTail->pNext=NULL;
    printf("请输入您需要生成的链表节点的个数:");
    scanf("%d",&len); 
    for(i=0;i<len;i++)
    {
        printf("请输入第%d个节点的值:",i+1);
        scanf("%d",&val);
        PNODE pNew =(PNODE)malloc(sizeof(NODE));//每次循环都分配一个节点。 
        if(pNew==NULL)
      {
        printf("分配失败,程序终止!\n");
        exit(-1);
      }
      pNew->data = val;
      pTail->pNext = pNew; 
      pNew->pNext = NULL;
      pTail = pNew;//指针pTail 时刻指向尾指针域 
    }
    return pHead; 
} 
void traverse_list(PNODE pHead)
{
    PNODE p=pHead->pNext;
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->pNext;
    }
    printf("\n");
    return;
}
bool is_empty(PNODE pHead)
{
    if(pHead->pNext==NULL)
       return true;
    else
       return false;
}
int length_list(PNODE pHead)
{
    PNODE p=pHead->pNext;
    int len=0;
    while(p!=NULL)
    {
        len++;
        p=p->pNext;
    }
    return len;
}
PNODE sort_list(PNODE pHead)
{
    int i,j,t;
    PNODE p,q;
    int len=length_list(pHead);
    for(i=0,p=pHead->pNext;i<len-1;i++,p=p->pNext)
    {
        for(j=i+1,q=p->pNext;j<len;j++,q=q->pNext)
        {
            if(p->data>q->data)
            {
                t=p->data;
                p->data=q->data;
                q->data=t;
            }
        }
    }
    //return;
}
//在pHead 所指向链表的第pos个节点的前面插入一个新的结点,该节点的值是val,并且pos是从1开始 
bool insert_list(PNODE pHead,int pos,int val)
{
    int i=0;
    PNODE p=pHead;
    while(p!=NULL&&i<pos-1)
    {
        p=p->pNext;
        i++;
    } 
    if(i>pos-1||p==NULL)
       return false;
    PNODE pNew=(PNODE)malloc(sizeof(NODE));
    if(pNew==NULL)
    {
        printf("动态分配内存失败\n");
        exit(-1); 
    }
    pNew->data=val;
    PNODE q=p->pNext;
    p->pNext=pNew;
    pNew->pNext=q;

    return true;
} 
bool delete_list(PNODE pHead,int pos,int *pVal)
{
    int i=0;
    PNODE p=pHead;
    while(p->pNext!=NULL&&i<pos-1)
    {
        p=p->pNext;
        i++;
    } 
    if(i>pos-1||p->pNext==NULL)
       return false;
    PNODE q=p->pNext;
    *pVal=q->data;
    p->pNext=p->pNext->pNext;
    free(q);
    q=NULL;

    return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值