| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1845 人关注过本帖, 1 人收藏
标题:链表插入操作案例测试给大家参考下
只看楼主 加入收藏
烟雨晨曦
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:150
专家分:599
注 册:2017-3-5
结帖率:100%
收藏(1)
已结贴  问题点数:20 回复次数:14 
链表插入操作案例测试给大家参考下
看见大家总是在问链表的问题,虽然简单,但里面坑还是很多的,总结了下给大家参考。
程序代码:
#include <stdio.h>
#include <malloc.h>

struct Test
{
    int nVal;
    struct Test* pNext;
};

struct Test* pHead = NULL;

//头部插入
void HeadInsert(int val)
{
    struct Test* pNew = NULL;
    pNew = (struct Test*)malloc(sizeof(struct Test));
    pNew->nVal = val;

    //将新节点的pNext指向头指针
    pNew->pNext = pHead;

    //将头指针重新指向新节点完成头部插入
    pHead = pNew;
}

//尾部插入
void TailInsert(int val)
{
    struct Test* pNew = NULL;
    struct Test* pTmp1 = pHead;
    struct Test* pTmp2 = pHead;
    pNew = (struct Test*)malloc(sizeof(struct Test));
    pNew->nVal = val;

    //跳出循环当前指针为空
    while(pTmp1 != NULL)
    {
        //记录pTmp1的前一个指针
        pTmp2 = pTmp1;

        //当前指针
        pTmp1 = pTmp1->pNext;
    }

    //注意不赋值为空遍历会访问未知空间错误
    pNew->pNext = NULL;

    //注意这里需要判断是否头指针为空
    if(pHead == NULL)
    {
        pHead = pNew;
    }
    else
    {
        //将当前指针的前一个指针的pNext指向新指针
        pTmp2->pNext = pNew;
    }
   

}


//任意位置插入
void Insert(int val, int pos)
{
    struct Test* pNew = NULL;
    struct Test* pTmp1 = pHead;
    struct Test* pTmp2 = pHead;
    int i = 1;
    pNew = (struct Test*)malloc(sizeof(struct Test));
    pNew->nVal = val;
    pNew->pNext = NULL;
    while(pTmp1 != NULL && i <= pos)
    {

        if(i == pos)
        {
            //将新节点的pNext指向当前结点
            pNew->pNext = pTmp1;

            //很重要
            if(i == 1)
            {
                //第一个位置直接头节点指向新节点
                pHead = pNew;
            }
            else
            {
                //将当前指针的pNext前一个指针指向新节点
                pTmp2->pNext = pNew;
            }

            return;

        }
        //记录pTmp1的前一个指针
        pTmp2 = pTmp1;

        //当前指针
        pTmp1 = pTmp1->pNext;

        i++;
    }
    
    //未找到插入位置处理
    if(i > pos || pTmp1 == NULL)
    {
        printf("位置未找到头部插入\n");
        pNew->pNext = pHead;
        pHead = pNew;
    }
}

void Traver()
{
    struct Test* pTmp = pHead;
    while(pTmp != NULL)
    {
        printf("%d ", pTmp->nVal);
        pTmp = pTmp->pNext;
    }
    printf("\n\n");
}

int main()
{
    int i = 0;

    printf("在0位置插入1000:\n");
    Insert(1000, 0);
    Traver();

    printf("尾部插入6-9:\n");
    for(i = 6; i < 10; i++)
    {
        TailInsert(i);
    }
    Traver();

    printf("头部插入0-5:\n");
    for(i = 0; i < 6; i++)
    {
        HeadInsert(i);
    }
    Traver();

    printf("尾部插入10-15:\n");
    for(i = 10; i < 16; i++)
    {
        TailInsert(i);
    }
    Traver();

   

    printf("在第1个位置插入111:\n");
    Insert(111, 1);
    Traver();

    printf("在第2个位置插入222:\n");
    Insert(222, 2);
    Traver();

    printf("在第100个位置插入100:\n");
    Insert(100, 100);
    Traver();

    printf("在第20个位置插入2000:\n");
    Insert(2000, 20);
    Traver();


    return 0;
}
图片附件: 游客没有浏览图片的权限,请 登录注册



[此贴子已经被作者于2017-3-17 23:42编辑过]

2017-03-17 23:12
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:10 
感觉插入与删除应该是先按要求查找到元素~然后再传入该元素所在的结构体的地址~
用双向链表插入和删除效率较高~直接传入结构体的指针地址就行了~

其实创建链表是属于尾部插入的一种~
当然~初学的用这个代码还是不错的~可以写写查找和删除的代码~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-03-18 00:32
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:10 
帮我看看这个逆序链表的函数原理吧
程序代码:
pdate reverselist(pdate head)
{
    if(head->next == NULL || head->next->next == NULL) 
    {
        return head;   /*链表为空或只有一个元素则直接返回*/
    }
    tdate *t = NULL;
    tdate *p = head->next;
    tdate *q = head->next->next;
    while(q != NULL)
    {       
      t = q->next;
      q->next = p;
      p = q;
      q = t;
     
    }
    /*此时q指向原始链表最后一个元素,也是逆转后的链表的表头元素*/
    head->next->next = NULL;  /*设置链表尾*/
    head->next = p;           /*调整链表头*/
    return head;
}
通过以下语句发现

printf("\n%p %p %p %p %p \n",head->next,head->next->next,head->next->next->next,head->next->next->next->next,head->next->next->next->next->next);

00392B68 00392BA8 00392BE8 00392C28 00392C68

00392C68 00392C28 00392BE8 00392BA8 00392B68

确实是实现了逆序对调  但是这个函数的原理就没看懂
尤其是
 while(q != NULL)
    {        
      t = q->next;
      q->next = p;
      p = q;
      q = t;
      
    }
这个循环   一般逆序不都是 首尾对调 首2 尾2对调 。。。。。。


DO IT YOURSELF !
2017-03-18 07:37
烟雨晨曦
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:150
专家分:599
注 册:2017-3-5
收藏
得分:0 
回复 3楼 wp231957
图片附件: 游客没有浏览图片的权限,请 登录注册

这个思路最主要的就是记录下第三个指针反转前两个指针,在记录下第三个指针反转前两个指针····
2017-03-18 08:10
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
回复 4楼 烟雨晨曦
我想看一下具体的逆序过程  可是下面代码 啥都看不到
程序代码:
pdate reverselist(pdate head)
{

    if(head->next == NULL || head->next->next == NULL) 
    {
        return head;   /*链表为空或只有一个元素则直接返回*/
    }
    tdate *t = NULL;
    tdate *p = head->next;
    tdate *q = head->next->next;
    while(q != NULL)
    {   
        t = q->next;
        q->next = p;
        p = q;
        q = t;
        pdate  p1=head->next;  //原始链表共初始化了8组数据
        pdate  p2=p1->next;
        pdate  p3=p2->next;
        pdate  p4=p3->next;
        pdate  p5=p4->next;
        pdate  p6=p5->next;
        pdate  p7=p6->next;
        pdate  p8=p7->next;
        printf("\n%p %p %p %p %p %p %p %p \n",p1,p2,p3,p4,p5,p6,p7,p8);      
    }
    /*此时q指向原始链表最后一个元素,也是逆转后的链表的表头元素*/
    head->next->next = NULL;  /*设置链表尾*/
    head->next = p;           /*调整链表头*/
    return head;
}
这段代码结果如下:
00392B68 00392BA8 00392BE8 00392C28 00392C68 00392CA8 00392CE8 00392D28

00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8

00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8

00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8

00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8

00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8

00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8

00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8 00392B68 00392BA8

00392D28 00392CE8 00392CA8 00392C68 00392C28 00392BE8 00392BA8 00392B68
除了第一行 和最后一行 能够看出来是完整的大对调 中间的过程都看不出来啊



DO IT YOURSELF !
2017-03-20 12:37
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
回复 4楼 烟雨晨曦
谢谢你这个图片制作花费了不少功夫 可是我可以说 没看懂吗

DO IT YOURSELF !
2017-03-20 12:39
烟雨晨曦
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:150
专家分:599
注 册:2017-3-5
收藏
得分:0 
回复 6楼 wp231957
你给的代码头指针没有逆序我改了一下,逆序过程你可以看一下, 不过最后会断掉因为指针已经不存在了,去掉打印信息就可以了,正常运行
图片附件: 游客没有浏览图片的权限,请 登录注册

程序代码:
#include <stdio.h>
#include <malloc.h>

typedef struct Link
{
    int nVal;
    struct Link* pNext;
    Link()
    :nVal(0)
    ,pNext(NULL)
    {}
}Link,* PLink;

PLink pHead = NULL;


void ReverseLink()
{
    if(pHead == NULL || pHead->pNext == NULL)
    {
        return;

    }
    PLink tmp = NULL;
    PLink pFirst = pHead;
    PLink pSecond = pHead->pNext;
    while(pSecond != NULL)
    {
      tmp = pSecond->pNext;
      printf("tmp:%d pSecond:%d pFirst:%d\n", tmp->nVal, pSecond->nVal, pFirst->nVal);   
      getchar();
      pSecond->pNext = pFirst;
      if(pFirst == pHead)
      {
              pFirst->pNext = NULL;
      }
      pFirst = pSecond;
      pSecond = tmp;
    }
    pHead = pFirst;

}

void Insert(int val)
{

    PLink pNew = NULL;
    pNew = (PLink)malloc(sizeof(Link));
    pNew->nVal = val;
    pNew->pNext = pHead;
    pHead = pNew;
}

void Travel()
{
    PLink pTmp = pHead;
    while(pTmp != NULL)
    {
        printf("%d ", pTmp->nVal);
        pTmp = pTmp->pNext;
    }
    printf("\n\n");
}

int main(int argc, char** argv)
{
        printf("创建链表:\n");
        for(int i = 0; i < 10; i++)
        {
            Insert(i);
        }
        Travel();
        printf("逆序后:\n");
        ReverseLink();
        Travel();


        return 0;
}



[此贴子已经被作者于2017-3-20 21:44编辑过]

2017-03-20 20:56
烟雨晨曦
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:150
专家分:599
注 册:2017-3-5
收藏
得分:0 
回复 6楼 wp231957
我又修改了一下这样你应该能看清楚了,配合上面那个
图片附件: 游客没有浏览图片的权限,请 登录注册
#include <stdio.h>
#include <malloc.h>

typedef struct Link
{
    int nVal;
    struct Link* pNext;
    Link()
    :nVal(0)
    ,pNext(NULL)
    {}
}Link,* PLink;

PLink pHead = NULL;

void Travel()
{
    PLink pTmp = pHead;
    while(pTmp != NULL)
    {
        printf("%d ", pTmp->nVal);
        pTmp = pTmp->pNext;
    }
    printf("\n\n");
}


void ReverseLink()
{
    if(pHead == NULL || pHead->pNext == NULL)
    {
        return;

    }
    PLink tmp = NULL;
    PLink pFirst = pHead;
    PLink pSecond = pHead->pNext;
    while(pSecond != NULL)
    {     

      tmp = pSecond->pNext;
      pSecond->pNext = pFirst;
      if(pFirst == pHead)
      {
              pFirst->pNext = NULL;
      }
      pHead = pFirst;
      Travel();
      pFirst = pSecond;
      pSecond = tmp;
    }
    pHead = pFirst;

}

void Insert(int val)
{

    PLink pNew = NULL;
    pNew = (PLink)malloc(sizeof(Link));
    pNew->nVal = val;
    pNew->pNext = pHead;
    pHead = pNew;
}



int main(int argc, char** argv)
{
        printf("创建链表:\n");
        for(int i = 0; i < 10; i++)
        {
            Insert(i);
        }
        Travel();
        printf("逆序后:\n");
        ReverseLink();
        Travel();

        return 0;
}
2017-03-20 21:41
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
我也弄一个~顺便熟悉一下~

程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define LEN sizeof (Node)

typedef struct Node
{
    int n;
    struct Node* next;
}Node,*PNode;

PNode Creat(PNode head);    //创建数据
PNode NewNode(int n);       //新加入结点
void Print(PNode p);        //输出节点
PNode Reverse(PNode p);     //链表逆序

int main()
{
    PNode head=NULL;
    head=NewNode(0);

    head=Creat(head);

    puts("创建结果如下:");
    Print(head);

    head=Reverse(head);
    puts("链表逆序如下:");
    Print(head);
    return 0;
}

PNode NewNode(int n)
{
    PNode p=(PNode)malloc(LEN);

    if (p==NULL)
    {
        puts("创建节点出错!");
        exit(0);
    }

    p->next=NULL;
    p->n=n;

    return p;
}

PNode Creat(PNode head)
{
    PNode p=head;
    int a=0;

    while (p->next) //把链表指针移向尾部~可以重复加入数据到链表尾部,提高链表利用率
        p=p->next;

    puts("请输入数据(输入0结束输入):");
    while (scanf("%d",&a)&&a)
        p=p->next=NewNode(a);

    return head;
}

void Print(PNode p)        //输出节点
{
    for (;p=p->next;printf("%d ",p->n));
    puts("");
}

PNode Reverse(PNode head)     //链表逆序
{
    PNode p1=head;
    PNode p2=head->next;
    PNode p3=NULL;

    if (head->next==NULL||head->next->next==NULL)
        return head;

    p3=p2->next;
    p2->next=NULL;

    while (p3)
    {
        p1=p2;
        p2=p3;
        p3=p3->next;
        p2->next=p1;
    }

    head->next=p2;

    return head;
}

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-03-20 23:01
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
参照你8楼的代码  我下面的代码 莫名其妙的多了几行数据  莫名其妙的少了几行数据
程序代码:
#include <stdio.h>
#include <malloc.h>

#define N 8

typedef struct date
{
    unsigned int month;
    unsigned int day;
    unsigned int year;
    struct date* next;
}tdate,*pdate;


pdate linkcre(void)
{
    pdate head,pfirst,psecond;
    tdate cr[8]=
    {
        {10,10,2000},{11,11,2012},{05,05,2005},{01,01,2006},{12,30,2016}
        ,{01,01,2005},{02,02,2008},{03,03,2009}
    };
    pfirst=(pdate)malloc(sizeof(tdate));
    head=pfirst;
    psecond=pfirst;
    int i;
    for(i=0;i<N;i++)
    {
        pfirst=(pdate)malloc(sizeof(tdate));
        pfirst->month=cr[i].month;
        pfirst->day=cr[i].day;
        pfirst->year=cr[i].year;
        pfirst->next=NULL;
        psecond->next=pfirst;
        psecond=pfirst;
    }
    return head;
}

void prnlist(pdate head)
{
    pdate pfirst=head->next;
    while(pfirst!=NULL)
    {
        printf("%6u%4u%4u\n",pfirst->year,pfirst->month,pfirst->day);
        pfirst=pfirst->next;
    }
}

pdate reverselink(pdate phead)
{
    if(phead == NULL || phead->next == NULL) return NULL;
    pdate tmp = NULL;
    pdate pfirst = phead;
    pdate psecond = phead->next;
    while(psecond != NULL)
    {    
      tmp = psecond->next;
      psecond->next = pfirst;
      if(pfirst == phead)  pfirst->next = NULL;
      phead = pfirst;
      prnlist(phead);
      pfirst = psecond;
      psecond = tmp;
    }
    phead = pfirst;
    return phead;
}


int main(int argc, char* argv[])
{
    pdate  head;
    head=linkcre();
    printf("////////////正常输出示例//////////////////\n");
    prnlist(head);
    head=reverselink(head);
    printf("////////////逆序输出示例//////////////////\n");
    prnlist(head);
    free(head);
    return 0;
}

/*
////////////正常输出示例//////////////////
  2000  10  10
  2012  11  11
  2005   5   5
  2006   1   1
  2016  12  30
  2005   1   1
  2008   2   2
  2009   3   3
345281684534528168453452816845
  2000  10  10
345281684534528168453452816845
  2012  11  11
  2000  10  10
345281684534528168453452816845
  2005   5   5
  2012  11  11
  2000  10  10
345281684534528168453452816845
  2006   1   1
  2005   5   5
  2012  11  11
  2000  10  10
345281684534528168453452816845
  2016  12  30
  2006   1   1
  2005   5   5
  2012  11  11
  2000  10  10
345281684534528168453452816845
  2005   1   1
  2016  12  30
  2006   1   1
  2005   5   5
  2012  11  11
  2000  10  10
345281684534528168453452816845
////////////逆序输出示例//////////////////
  2008   2   2
  2005   1   1
  2016  12  30
  2006   1   1
  2005   5   5
  2012  11  11
  2000  10  10
345281684534528168453452816845
*/



DO IT YOURSELF !
2017-03-21 13:11
快速回复:链表插入操作案例测试给大家参考下
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.021854 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved