链表算法——考研数据结构

文章目录

  • 链表
    • 1. 定义一个链表
    • 2. 插入数据
      • 头添加
      • 尾添加
      • 中间插入
    • 3. 查找节点
      • 根据下标查找节点
      • 根据数据查找节点
    • 4. 删除节点
      • 头删除
      • 尾删除
      • 中间删除
    • 5. 修改元素
      • 修改制定数据
      • 修改指定下标的数据
  • 双向链表
    • 双向链表的定义

链表

1. 定义一个链表

  1. 数据项
  2. 下一个节点的地址
struct node
{
   int data ;
   struct node* next ;
}

2. 插入数据

头添加

void add_to_head(struct node** , struct node** end , int idata)
{
  // 创建节点,为新节点申请空间
  struct node* temp = (struct node*)malloc(sizeof(struct node));
  // 节点成员赋值
  if(temp != null) // 可能会出现申请节点失败的现象
  {
    temp->data = idata;
    ptemp->next = null; //尾节点赋值为空很重要
    // 新节点连接到合适的位置
    if() // 如果初始链表为空,添加节点就是即使头节点又是尾节点
    {
      *end = temp;
      //*head = temp;
    }
    else
    {
      temp->next = *head;
      // *head = temp; 
    }
    // 把新节点设置为头节点
    *head = temp ;
  }     
  
}

尾添加

void add_to_end(struct node** , struct node** end , int data)
{
    // 创建节点,为新节点申请空间
  struct node* temp = (struct node*)malloc(sizeof(struct node));
  // 节点成员赋值
  if(temp != null) // 可能会出现申请节点失败的现象
  {
    temp->data = idata;
    ptemp->next = null; //尾节点赋值为空很重要
    // 新节点连接到合适的位置
    
    // 连上去
    if(*head == null) // 若果链表为空
    {
      *head = temp; 
      // *end = temp; 
    }
    else //如果链表不为空,则连到尾部
    {
      (*end)->next = temp;
      // *end = temp; 
    }
    *end = temp; 
} 

中间插入

void add_to_middle(struct node** head, struct node** end, int index , int idata)
{
  // 创建节点,为新节点申请空间
  struct node* temp = (struct node*)malloc(sizeof(struct node));
  // 节点成员赋值
  if(temp != null) // 可能会出现申请节点失败的现象
  {
    temp->data = idata;
    ptemp->next = null; //尾节点赋值为空很重要
    
    //根据下标超入指定位置
    if(index == 0) //若果下标为0,添加到头部
    {
      // 传递的参数是,形参
      add_to_head(head,end,idata);
    }
    else //根据下标查找到节点添加
    {
      struct node* temp = findbyindex(*head,index);
      if(temp != null)
      {
        // 申请临时空间
        struct node* pt =(struct node*)malloc(sizeof(struct node));
        // 将节点插入
        if(pt != null)
        {
          // 为临时申请的节点赋值
          pt->data = idata;
          pt->next = null;
          
          // 连接上,先练后段
          pt->next = temp->next;
          temp->next = pt;
        }
      }
    }
}

3. 查找节点

根据下标查找节点

int find_by_index(struct node* head , int index)
{
    int num = 1; // 下标从1开始,链表下标没有0
    while(head!=null)
    {
      if(index == num)
      {
        return head;
      }
      num++;
      head=head->next;
    }
    return null;
}

根据数据查找节点

int find_by_index(struct node* head , int index)
{
    while(head!=null)
    {
      if(head->data == idata)
      {
        return head;
      }
      head=head->next;
    }
    return null;
}

4. 删除节点

头删除

void delete_head(struct node** head , struct node** end)
{
  if(*head == null)
  {
    return ;
  } 
  if((*head)->next == null)
  {
    free(*head);
  }
  else
  {
    // 申请一个临时节点来记录要删除的新节点
    struct node* pt = *head; 
    // 把当前头节点的下一个节点设置为新的头节点
    head = (*head)->next; 
    // 释放原来的头节点,即刚刚的临时节点
    free(pt);
  }
 
}

尾删除

void delete_end(struct Node** Head, struct Node** End)
{
	if (*Head == NULL)
	{
		return;
	}
	//* pHea == *pEnd,此时只有一个结点,直接释放,但是要把下一个节点设置为NULL
	if ((*pHead)->pNext == NULL) 
	{
		//释放结点,一定要头尾都置为null
		free(*pHead);  
		*pHead = NULL;
		*pEnd = NULL;
	}
	else
	{
		// 找到倒数第二个节点,目的是为了把最后一个节点的下一个设置为NULL
		struct Node* pt = *pHead;  //先定义一个中间变量来装要删除的头结点
		while (pt->next != *end) // 当pT->pNext为*pEnd的时候,pT为倒数第二个节点
		{
			pt = pt->next;
		}
		// 找到之后
		free(*end);  // 释放尾,而不是释放pT
		*end = pt;  //再把尾结点设置为找到的倒数第二个结点
		(*end)->next = NULL; // 最重要的是把新的pEnd->pNext设置为NULL

	}
}

中间删除

void delete_middle(struct node** head, struct node** end,int idata)
{
  // 严谨的话可以判断一下,数据是不是头尾节点,如果是直接点用头删除函数、尾删除函数
  
  // 建立一个新节点来装头节点来进行循环查找,否则头节点指针会被修好
  struct node* temp = *head;
  // 如果下一个节点不为null,就要继续查找,前面已经判断的头和尾时的问题
  while(temp->next != null)
  {
    if(temp->next->data == idata)
    {
      break; // 找到数据节点,退出循环    
    }
    // 进行下一次循环查找
    temp=temp->next;
  }
  
  // 这时如果找到数据,则为temp->next
  if(temp->next != null)
  {
    // 记录要删除的节点,让pt指向下一个要删除节点的下一个
    struct node* pt = temp->next;
    // 这样就能把pt节点抠出来
    temp->next = pt->next;
    free(pt);
  }
  else // 如果下一个节点尾点为null,则这个节点是尾节点,前面已经讨论过头尾节点的问题了
  {
    printf("查无此节点")}
}

5. 修改元素

修改制定数据

// 用data2覆盖data1的值
void change_by_daya(struct node* head , int data1 , int data2 )
{
  struct node* temp = find_by_data(head,data1)
  {
    if(temp. != null)
    {
      temp->data = data2 ;
    }
  }
}

修改指定下标的数据

void change_by_index(struct node* head , int index , int data)
{
  // 通过查找指定下标函数,找到节点地址
  struct node* temp = find_by_index(phead,data)
  if(temp != null)
  {
    temp->data = data;
  }
}

双向链表

双向链表的定义

struct Node
{
	int Data;  //数据结点
	struct Node* PNext;  // 下一个结点的地址
	struct Node* Pre;  // 上一个结点的地址
};

你可能感兴趣的:(数据结构,数据结构,c语言)