ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

单链表

2021-07-06 20:33:39  阅读:187  来源: 互联网

标签:InsertList pp 单链 ee LL 结点 printf


1、定义一个结构体

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

typedef int ElemType;     // 自定义链表的数据元素为整数。

typedef struct LNode
{
  ElemType data;       // 存放结点的数据元素。
  struct LNode *next;  // 指向下一个结点的指针。
}LNode,*LinkList;


int main()
{
  return 0;
}

2、初始化链表

// 初始化链表LL,返回值:失败返回NULL,成功返回头结点的地址。
LNode *InitList1();

int main()
{
  LinkList LL=NULL; // 声明链表指针变量。
  LL=InitList1();     // 初始化链表。
  printf("LL=%p\n",LL);

  return 0;
}

// 初始化链表LL,返回值:失败返回NULL,成功返回头结点的地址。
LNode *InitList1()
{
  LNode *head = (LNode *)malloc(sizeof(LNode));  // 分配头结点。

  if (head == NULL) return NULL;  // 内存不足,返回失败。

  head->next=NULL;  // 头结点的下一结点暂时不存在,置空。

  return head;
}

三、创建一个数据元素。


int main()
{
  LinkList LL=NULL; // 声明链表指针变量。
  LL=InitList1();     // 初始化链表。
  printf("LL=%p\n",LL);

  ElemType ee;      // 创建一个数据元素。

  return 0;
}

4、单链表的插入

// 在链表LL的第ii个位置插入元素ee,返回值:0-失败;1-成功。
int  InsertList(LinkList LL, unsigned int ii, ElemType *ee);   

int main()
{
  LinkList LL=NULL; // 声明链表指针变量。
  LL=InitList1();     // 初始化链表。
  printf("LL=%p\n",LL);

  ElemType ee;      // 创建一个数据元素。

  printf("在表中插入元素(1、2、3、4、5、6、7、8、9、10)。\n");
  ee=1;  InsertList(LL, 1, &ee);
  ee=2;  InsertList(LL, 1, &ee);
  ee=3;  InsertList(LL, 1, &ee);
  ee=4;  InsertList(LL, 1, &ee);
  ee=5;  InsertList(LL, 1, &ee);
  ee=6;  InsertList(LL, 1, &ee);
  ee=7;  InsertList(LL, 1, &ee);
  ee=8;  InsertList(LL, 1, &ee);
  ee=9;  InsertList(LL, 1, &ee);
  ee=10; InsertList(LL, 1, &ee);

  printf("length=%d\n",LengthList(LL));
  return 0;
}

// 在链表LL的第ii个位置插入元素ee,返回值:0-失败;1-成功。
int InsertList(LinkList LL, unsigned int ii, ElemType *ee)
{
  if ( (LL == NULL) || (ee == NULL) ) { printf("链表LL或元素ee不存在。\n"); return 0; } // 判断表和元素是否存在。

  // 判断插入位置是否合法
  if (ii < 1) { printf("插入位置(%d)不合法,应该在大于0。\n",ii); return 0; }

  // 要在位序ii插入结点,必须找到ii-1结点。
  LNode *pp=LL;  // 指针pp指向头结点,逐步往后移动,如果为空,表示后面没结点了。
  int kk=0;      // kk指向的是第几个结点,从头结点0开始,pp每向后移动一次,kk就加1。

  while ( (pp != NULL) && (kk < ii-1) )
  {
    pp=pp->next; kk++;

    printf("pp=%p,kk=%d\n",pp,kk);
  }

  if ( pp==NULL ) { printf("位置(%d)不合法,超过了表长。\n",ii); return 0; }

  LNode *tmp = (LNode *)malloc(sizeof(LNode));  // 分配一个结点。
  if (tmp == NULL) return 0;  // 内存不足,返回失败。
  
  // 考虑数据元素为结构体的情况,这里采用了memcpy的方法而不是直接赋值。
  memcpy(&tmp->data,ee,sizeof(ElemType));

  // 处理next指针。
  tmp->next=pp->next;
  pp->next=tmp;

  return 1;
}

5、打印表中全部的元素

void PrintList(LinkList LL)

int main()
{
  LinkList LL=NULL; // 声明链表指针变量。
  LL=InitList1();     // 初始化链表。
  printf("LL=%p\n",LL);

  ElemType ee;      // 创建一个数据元素。

  printf("在表中插入元素(1、2、3、4、5、6、7、8、9、10)。\n");
  ee=1;  InsertList(LL, 1, &ee);
  ee=2;  InsertList(LL, 1, &ee);
  ee=3;  InsertList(LL, 1, &ee);
  ee=4;  InsertList(LL, 1, &ee);
  ee=5;  InsertList(LL, 1, &ee);
  ee=6;  InsertList(LL, 1, &ee);
  ee=7;  InsertList(LL, 1, &ee);
  ee=8;  InsertList(LL, 1, &ee);
  ee=9;  InsertList(LL, 1, &ee);
  ee=10; InsertList(LL, 1, &ee);

  PrintList(LL);

  return 0;
}

// 打印链表中全部的元素。
void PrintList(LinkList LL)
{
  if (LL == NULL) { printf("链表LL不存在。\n"); return; } // 判断链表是否存在。

  LNode *pp=LL->next;  // 从第1个结点开始。

  while (pp != NULL)
  {
    printf("%-3d", pp->data);  // 如果元素ee为结构体,这行代码要修改。
    pp=pp->next;
  }

  printf("\n");
}

6、链表尾部插入元素

int PushBack(LinkList LL, ElemType *ee);

int main()
{
  LinkList LL=NULL; // 声明链表指针变量。
  LL=InitList1();     // 初始化链表。
  printf("LL=%p\n",LL);

  ElemType ee;      // 创建一个数据元素。

  printf("在表中插入元素(1、2、3、4、5、6、7、8、9、10)。\n");
  ee=1;  InsertList(LL, 1, &ee);
  ee=2;  InsertList(LL, 1, &ee);
  ee=3;  InsertList(LL, 1, &ee);
  ee=4;  InsertList(LL, 1, &ee);
  ee=5;  InsertList(LL, 1, &ee);
  ee=6;  InsertList(LL, 1, &ee);
  ee=7;  InsertList(LL, 1, &ee);
  ee=8;  InsertList(LL, 1, &ee);
  ee=9;  InsertList(LL, 1, &ee);
  ee=10; InsertList(LL, 1, &ee);

  printf("在表尾插入元素11。\n");
  ee=11; PushBack(LL, &ee);
  PrintList(LL);

  return 0;
}

// 在链表LL的尾部插入元素ee,返回值:0-失败;1-成功。
int PushBack(LinkList LL, ElemType *ee)
{
  if ( (LL == NULL) || (ee == NULL) ) { printf("链表LL或元素ee不存在。\n"); return 0; } // 判断表和元素是否存在。

  LNode *pp=LL;  // 从头结点开始。

  // 找到最后一个结点。
  while (pp->next != NULL) pp=pp->next;
  
  LNode *tmp = (LNode *)malloc(sizeof(LNode));  // 分配一个结点。
  if (tmp == NULL) return 0;  // 内存不足,返回失败。
  
  // 考虑数据元素为结构体的情况,这里采用了memcpy的方法而不是直接赋值。
  memcpy(&tmp->data,ee,sizeof(ElemType));

  // 处理next指针。
  tmp->next=NULL;
  pp->next=tmp;

  return 1;
}

7、删除某个节点

int  DeleteNode(LinkList LL, unsigned int ii);

int main()
{
  LinkList LL=NULL; // 声明链表指针变量。
  LL=InitList1();     // 初始化链表。
  printf("LL=%p\n",LL);

  ElemType ee;      // 创建一个数据元素。

  printf("在表中插入元素(1、2、3、4、5、6、7、8、9、10)。\n");
  ee=1;  InsertList(LL, 1, &ee);
  ee=2;  InsertList(LL, 1, &ee);
  ee=3;  InsertList(LL, 1, &ee);
  ee=4;  InsertList(LL, 1, &ee);
  ee=5;  InsertList(LL, 1, &ee);
  ee=6;  InsertList(LL, 1, &ee);
  ee=7;  InsertList(LL, 1, &ee);
  ee=8;  InsertList(LL, 1, &ee);
  ee=9;  InsertList(LL, 1, &ee);
  ee=10; InsertList(LL, 1, &ee);

  printf("在表尾插入元素11。\n");
  ee=11; PushBack(LL, &ee);
  PrintList(LL);

  printf("删除表中第7个结点。\n");
  DeleteNode(LL,7); PrintList(LL);

  return 0;
}



// 删除链表LL中的第ii个结点,返回值:0-位置ii不合法;1-成功。
int  DeleteNode(LinkList LL, unsigned int ii)  
{
  if (LL == NULL) { printf("链表LL不存在。\n"); return; } // 判断链表是否存在。

  // 判断删除位置是否合法
  if (ii < 1) { printf("删除位置(%d)不合法,应该在大于0。\n",ii); return 0; }

  // 要删除位序ii结点,必须找到ii-1结点。
  LNode *pp=LL;  // 指针pp指向头结点,逐步往后移动,如果为空,表示后面没结点了。
  int kk=0;      // kk指向的是第几个结点,从头结点0开始,pp每向后移动一次,kk就加1。

  while ( (pp != NULL) && (kk < ii-1) )
  {
    pp=pp->next; kk++;
  }

  // 注意,以下行的代码与视频中的不一样,视频中的是 if ( pp==NULL ),有bug。
  if ( pp->next==NULL ) { printf("位置(%d)不合法,超过了表长。\n",ii); return 0; }

  LNode *tmp=pp->next;  // tmp为将要删除的结点。
  pp->next=pp->next->next;   // 写成p->next=tmp->next更简洁。

  free(tmp);

  return 1;
}

8、删除末尾的节点

int PopBack(LinkList LL)

int main()
{
  LinkList LL=NULL; // 声明链表指针变量。
  LL=InitList1();     // 初始化链表。
  printf("LL=%p\n",LL);

  ElemType ee;      // 创建一个数据元素。

  printf("在表中插入元素(1、2、3、4、5、6、7、8、9、10)。\n");
  ee=1;  InsertList(LL, 1, &ee);
  ee=2;  InsertList(LL, 1, &ee);
  ee=3;  InsertList(LL, 1, &ee);
  ee=4;  InsertList(LL, 1, &ee);
  ee=5;  InsertList(LL, 1, &ee);
  ee=6;  InsertList(LL, 1, &ee);
  ee=7;  InsertList(LL, 1, &ee);
  ee=8;  InsertList(LL, 1, &ee);
  ee=9;  InsertList(LL, 1, &ee);
  ee=10; InsertList(LL, 1, &ee);

  printf("在表尾插入元素11。\n");
  ee=11; PushBack(LL, &ee);
  PrintList(LL);

  printf("删除表中第7个结点。\n");
  DeleteNode(LL,7); PrintList(LL);

  printf("删除表中最后一个结点。\n");
  PopBack(LL); PrintList(LL);

  return 0;
}

// 删除链表LL中最后一个结点,返回值:0-位置不合法;1-成功。
int PopBack(LinkList LL)
{
  if ( LL == NULL ) { printf("链表LL不存在。\n"); return 0; } // 判断表和元素是否存在。

  // 必须加上这个判断,否则下面的循环pp->next->next不成立。
  if ( LL->next == NULL) { printf("链表LL为空,没有尾结点。\n"); return 0; } // 判断表是否为空。

  // 要删除最后一个结点,必须找到最后一个结点的前一个结点。

  LNode *pp=LL;  // 从第0个结点开始。

  // 找到倒数第二个结点(包括头结点)。
  while (pp->next->next != NULL) pp=pp->next;
 
  // 释放最后一个结点。
  free(pp->next);
  pp->next=NULL;

  return 1;
}

9、查询某个节点的地址

LNode *LocateNode(LinkList LL, unsigned int ii);

int main()
{
  LinkList LL=NULL; // 声明链表指针变量。
  LL=InitList1();     // 初始化链表。
  printf("LL=%p\n",LL);

  ElemType ee;      // 创建一个数据元素。

  printf("在表中插入元素(1、2、3、4、5、6、7、8、9、10)。\n");
  ee=1;  InsertList(LL, 1, &ee);
  ee=2;  InsertList(LL, 1, &ee);
  ee=3;  InsertList(LL, 1, &ee);
  ee=4;  InsertList(LL, 1, &ee);
  ee=5;  InsertList(LL, 1, &ee);
  ee=6;  InsertList(LL, 1, &ee);
  ee=7;  InsertList(LL, 1, &ee);
  ee=8;  InsertList(LL, 1, &ee);
  ee=9;  InsertList(LL, 1, &ee);
  ee=10; InsertList(LL, 1, &ee);

  printf("在表尾插入元素11。\n");
  ee=11; PushBack(LL, &ee);
  PrintList(LL);

  printf("删除表中第7个结点。\n");
  DeleteNode(LL,7); PrintList(LL);

  printf("删除表中最后一个结点。\n");
  PopBack(LL); PrintList(LL);

  if ( (tmp=LocateNode(LL,3)) != NULL)
  printf("第3个结点的地址是=%p,ee=%d\n",tmp,tmp->data);

  return 0;
}


// 获取链表中第ii个结点,成功返回结点的地址,失败返回空。
// 注意,ii可以取值为0,表示头结点。
LNode *LocateNode(LinkList LL, unsigned int ii)
{
  if ( LL == NULL ) { printf("链表LL不存在。\n"); return NULL; } // 判断表和元素是否存在。
  
  LNode *pp=LL;  // 指针pp指向头结点,逐步往后移动,如果为空,表示后面没结点了。
  int kk=0;      // kk指向的是第几个结点,从头结点0开始,pp每向后移动一次,kk就加1。

  while ( (pp != NULL) && (kk < ii) )
  { 
    pp=pp->next; kk++; 
  }

  if ( pp==NULL ) { printf("位置(%d)不合法,超过了表长。\n",ii); return NULL; }

  return pp;
}

10、查询元素在链表LL上节点地址

LNode *LocateElem(LinkList LL, ElemType *ee);

int main()
{
  LinkList LL=NULL; // 声明链表指针变量。
  LL=InitList1();     // 初始化链表。
  printf("LL=%p\n",LL);

  ElemType ee;      // 创建一个数据元素。

  printf("在表中插入元素(1、2、3、4、5、6、7、8、9、10)。\n");
  ee=1;  InsertList(LL, 1, &ee);
  ee=2;  InsertList(LL, 1, &ee);
  ee=3;  InsertList(LL, 1, &ee);
  ee=4;  InsertList(LL, 1, &ee);
  ee=5;  InsertList(LL, 1, &ee);
  ee=6;  InsertList(LL, 1, &ee);
  ee=7;  InsertList(LL, 1, &ee);
  ee=8;  InsertList(LL, 1, &ee);
  ee=9;  InsertList(LL, 1, &ee);
  ee=10; InsertList(LL, 1, &ee);

  printf("在表尾插入元素11。\n");
  ee=11; PushBack(LL, &ee);
  PrintList(LL);

  printf("删除表中第7个结点。\n");
  DeleteNode(LL,7); PrintList(LL);

  printf("删除表中最后一个结点。\n");
  PopBack(LL); PrintList(LL);

  if ( (tmp=LocateNode(LL,3)) != NULL)
  printf("第3个结点的地址是=%p,ee=%d\n",tmp,tmp->data);

  ee=8;
  if ( (tmp=LocateElem(LL,&ee)) != NULL)
    printf("元素值为8的结点的地址是=%p\n",tmp);
  else
    printf("元素值为8的结点的地址是NULL,没找着。\n");

  return 0;
}


// 查找元素ee在链表LL中的结点地址,如果没找到返回NULL,否则返回结点的地址。
LNode *LocateElem(LinkList LL, ElemType *ee)
{
  LNode *pp=LL->next;  // 从第1个数据结点开始。

  while (pp != NULL)
  {
    // 如果数据元素是结构体,以下代码要修改。
    if (pp->data == *ee) return pp;

    pp = pp->next;
  }

  return NULL;
}

标签:InsertList,pp,单链,ee,LL,结点,printf
来源: https://www.cnblogs.com/lnterpreter/p/14977777.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有