单链表的代码实现 C/C++

1. 静态链表
#include<iostream>
using namespace std;
struct Node
{
   int num;                //数据域
   struct Node *next;      //指针域 该指针指向结构体类型
};
int main()
{
   //创建三个结点
   struct Node Node1 = { 1, NULL };
   struct Node Node2 = { 2, NULL };
   struct Node Node3 = { 3, NULL };
   //建立三个结点之间的联系
   Node1.next = &Node2;
   Node2.next = &Node3;
   //遍历打印
   struct Node *cur = &Node1;      //定义一个当前指针指向第一个结点
   while (cur)
   {
      cout << cur->num<<" ";
      cur = cur->next;
   }
 system("pause");
}

以上创建节点并建立联系的两部分可以合并成一个部分,代码如下:

 //构建节点的同时,建立了联系
 Node Node3 = { 3, NULL };
 Node Node2 = { 2, &Node3 };       //注意取地址符
 Node Node1 = { 1, &Node2 };
 //创建头节点
 Node *headNode = &Node1;          //头节点只需要首节点的地址即可,无需数据
 //访问链表数据
 //创建一个移动的指针
 Node *cur = headNode;
 while (cur)
 {
  printf("%d\n", cur->num);
  cur = cur->next;
 }
2. 动态链表

链表中的对象,一般都是动态创建的。
比如,当用户需要添加一个对象时,从控制台输入信息,如何创建一个对象,插入到链表。
那么对象从哪儿来??
从malloc或者new开始

C语言
c语言中采用malloc,动态创建的对象生命期,自malloc之时生效,到free之后失效。

// 代码说明
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;

//以上只是单个结点的创建,并没有实现构造每个结点之间的联系 //如何创建联系?? //通过以下步骤:
// 1. 构造结点类型
(要明白什么时候用数组/结构体,数组:类型相同的数据;结构体:类型不同的数据)
struct Node
{
数据域;
指针域;
}
// 2.创建表头
struct Node* createList()
// 3. 创建结点
struct Node* createNode(int data)
// 4. 构造联系
void insertListByHead(struct Node* headNode, int data)
{
struct Node* newNode = createNode(data); // 参数data只是int类型,通过createNode(data)将其转换成结点类型
}

在这里插入图片描述

C语言代码实现
#include<stdlib.h>
#include<stdio.h>

//动态链表 堆区
struct Node
{
    int data;
    struct Node* next;
};

//创建一个表头(不存储数据)   结构体变量
struct Node* createList()
{
    //表头
    struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
    //变量 初始化头节点
    headNode->next = NULL;
    return headNode;
}

//创建节点(存储数据,用户传入)  结构体变量
struct Node* createNode(int data)
{
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    //变量 初始化每个节点(将传入的每个数据转换成节点)
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

//头插法(指定头节点为headNode的链表)
void insertListByHead(struct Node* headNode, int data)
{
     //将传入的data转换成节点
     struct Node* newNode = createNode(data);
     newNode->next = headNode->next;
     headNode->next = newNode;
}

//尾插法
void insertListByTail(struct Node* headNode, int data)
{
     struct Node* newNode = createNode(data);
     struct Node* cur = headNode;      
     while (cur->next != NULL)
     {
         cur = cur->next;
     }
     cur->next = newNode;
     newNode->next = NULL;
}

//指定位置插入
void insertListByAppoin(struct Node* headNode, int data, int pos)
{
    struct Node* newNode = createNode(data);
    //定义两个指针,一个cur指针,指向第一个节点;一个pre指针,指向头节点
    struct Node* cur = headNode->next;  
    struct Node * pre = headNode;
    int count = 1;
    while (cur != NULL && count < pos )
    {
        count += 1;
	   pre = cur;
	   cur = cur->next;
    }
 /*   //1. 针对传入的posData参数 > 链表节点个数,程序会把它当作“未找到指定位置”
    if (cur == NULL)
    {
       printf("未找到指定位置");
  	  return;
    }
    else 
    {
	  newNode->next = cur;
      pre->next = newNode;
    }
 */
 //2. 如果传入的posData参数 > 链表节点个数,程序会把它当作尾插法
     newNode->next = cur;
     pre->next = newNode;
}

//头删法
void deleteListByHead(struct Node* headNode)
{
   //如果只有一个头节点,无法删除
   if (headNode->next == NULL)
    {
      printf("无法删除");
 	 return;
    }
 	 struct Node* cur = headNode->next;
 	 headNode->next = cur->next;
}

//尾删法
void deleteListByTail(struct Node* headNode)
{
  //如果只有一个头节点,无法删除
   if (headNode->next == NULL)
    {
      printf("无法删除");
      return;
    }
   struct Node* cur = headNode->next;
   struct Node* pre = headNode;
   if (cur->next!= NULL)
    {
 	  pre = cur;
  	  cur = cur->next;
 	}
   pre->next = NULL;
}

//指定位置删除
void deleteListByAppoin(struct Node* headNode, int pos)
{
  //如果只有一个头节点,无法删除
   if (headNode->next == NULL || pos < 1)
 	{
  	  printf("无法删除");
  	  return;
     }
   int count = 1;
   struct Node* cur = headNode->next;
   struct Node* pre = headNode;
   while (count < pos)
    {
       count += 1;
  	  pre = cur;
  	  cur = cur->next;
    }
 //传入的参数pos越界,超出链表长度
   if (cur == NULL)
   {
      printf("无法找到指定位置\n");
      return;
   }
   else
   {
      pre->next = cur->next;
   }
}

//遍历打印节点(指定以headNode头节点开始的链表)
void printList(struct Node* headNode)
{
    struct Node* cur = headNode->next;    //当前指针指向下一个节点
    while (cur)
 	{
  	   cout << cur->data << endl;
        cur = cur->next;
     }
}

int main()
{
   struct Node* list = createList();     //创建链表,返回表头
   insertListByHead(list,1);
   insertListByHead(list,2);
   insertListByHead(list,3);
   insertListByTail(list,4);
   printList(list);
   deleteListByAppoin(list, 1);
   insertListByAppoin(list, 999, 4);
   printList(list);
   system("pause");
}

其它问题
访问成员时,什么时候用“->”, 什么时候用“.”???
指针类型用“->”,普通变量用“.”。
例子如下:

struct node
{
 int a;
 struct node* next;
};
int main()
{
 //结构体普通变量,访问成员用“."
 struct node bianliang1, bianliang2;
 bianliang1.a = 10;
 bianliang1.next = &bianliang2;   //注意加地址符
 cout << bianliang1.a << endl;    
 //结构体指针变量,访问成员用“->"
 //定义的指针指向上一个变量
 struct node *p1 = &bianliang1, *p2 = &bianliang2;
 //(*p1).next = p2;   不采用这种方式,麻烦
 p1->a = 20;
 p1->next = p2;
 cout << bianliang1.a << endl;      //内容通过指针被修改
 cout << p1->a << endl;
 system("pause");
}

结果

在这里插入图片描述

3.单链表的一些算法

1)实现从尾到头打印单链表(递归)

void nixuprint(struct Node* headNode)  //传入链表,链表的构建见上面的代码
{
 if (headNode == NULL || headNode->pnext == NULL)
 {
    return;        
 }
 Node *nextNode = headNode->pnext;
 //cout << nextNode->num << endl;   //顺序打印
 nixuprint(nextNode);     
 cout << nextNode->num << endl;   //逆序打印
 }

未完待续。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值