单链表经典问题3

单链表中节点类型定义如下:

typedef struct link {
 int data;
 link* next;
}node,*linklist;

1.试编写在带头节点的单链表L中删除一个最小值节点的高效算法(假设最小值节点时唯一的)

void delete_MinX(linklist& L) {
//试编写在带头节点的单链表L中删除一个最小值节点的高效算法(假设最小值节点时唯一的)
 node* min_pre = L;//记录最小节点的前一个节点
 node* min_p=L->next;//用于指向最小值节点
 node* pre=L;//记录遍历时节点的前一个节点
 node* p = L->next;
 while (p != NULL){
  if (p->data <min_p->data) {
   min_pre = pre;
   min_p = p;
  }
  pre = pre->next;
  p = p->next;
 }
 min_pre->next = min_p->next;
 cout << min_p->data<<endl;
}

2.设在一个带头节点的单链表中所有元素节点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素

void delete_between(linklist& L, int x, int y) {
//设在一个带头节点的单链表中所有元素节点的数据值无序,试编写一个函数,
//删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素
 node* pre = L;
 node* p = L->next;
 while (p != NULL) {
  if (p->data <= y && p->data >= x) {
   pre->next = p->next;
   p = p->next;
   //free(p);
  }
  else {
   pre = p;
   p = p->next;
  }
 }
}

3.有一个带头节点的单链表L,设计一个算法使其元素递增有序

void sort(linklist& L) {
//有一个带头节点的单链表L,设计一个算法使其元素递增有序
 //方法1:断链,逐个插入法;
 if (L->next == NULL) {
  return;
 }
 node* p = L->next;
 node* rear = p->next;
 p->next = NULL;//断链,让其只剩下一个节点,最后采用插入法;
 p = rear;
 while (p != NULL) {
  rear = p->next;
  node* q_pre = L;//指向被插入位置的前一个节点
  node* q = L->next;
  while (q != NULL&&q->data<p->data) {
   q_pre = q;
   q = q->next;
  }
  p->next = q_pre->next;
  q_pre->next = p;
  p = rear;
 }
 //方法2:交换元素值
 /*int length = 0;
 node* p = L->next;
 while (p != NULL) {
  length++;
  p = p->next;
 }
 if (length <= 1) {
  return;
 }
 node* pre = L->next;;
 p = pre->next;
 int t = 1;
 while (t < length) {
  int tt = 0;
  pre = L->next;
  p = pre->next;
  while (tt < length - t) {
   if (pre->data > p->data) {
    int exchange = pre->data;
    pre->data = p->data;
    p->data = exchange;
   }
   pre = p;
   p = p->next;
   tt++;
  }
  t++;
 }*/
}

4.给定两个单链表,编写算法找出两个链表的公共节点。

linklist Common(linklist A, linklist B) {
//给定两个单链表,编写算法找出两个链表的公共节点。
//算法思路:先走K步,然后一同走;
 int length1 = 0;
 int length2 = 0;
 node* p = A->next;
 node* q = B->next;
 while (p != NULL) {
  p = p->next;
  length1++;
 }
 while (q != NULL) {
  q = q->next;
  length2++;
 }
 int k;
 if (length1 >= length2) {
  k = length1 - length2;
  p = A->next;
  while (k > 0) {
   p = p->next;
   k--;
  }
  q = B->next;
 }
 else {
  k = length2 - length1;
  q = B->next;
  while (k > 0) {
   q = q->next;
   k--;
  }
  p = A->next;
 }
 while (p!=NULL&&q!=NULL&&p->data != q->data) {//同时走找公共节点
  p = p->next;
  q = q->next;
 }
 cout << p->data;
 if (p->data == q->data) {
  return p;
 }
 return NULL;
}

5.给定一个带表头节点的单链表,设head为头指针,试写出算法:按递增次序输出单链表中各结点的数据元素,并释放结点所占的存储空间

void fun1(linklist& head) {
//给定一个带表头节点的单链表,设head为头指针,试写出算法:
//按递增次序输出单链表中各结点的数据元素,并释放结点所占的存储空间
//不允许数组作为辅助空间
 while (head->next != NULL) {
  node* min_pre = head;
  node* min_p = head->next;//设刚开始最小值就是第一个结点
  node* pre = head;
  node* p = head->next;
  while (p != NULL) {
      if (p->data < min_p->data) {
    min_p = p;
    min_pre = pre;
   }
   pre = p;
   p = p->next;
  }
  cout << min_p->data << endl;
  min_pre->next = min_p->next;
 }
}

6.将一个带头节点的单链表分成两个单链表,A存放奇数结点,B存放偶数结点
在这里插入图片描述

void fun2(linklist& L) {
//将一个带头节点的单链表分成两个单链表,A存放奇数结点,B存放偶数结点
 node* la = (node*)malloc(sizeof(node*));//创建链表A的头节点
 node* lb = (node*)malloc(sizeof(node*));//创建链表B的头节点
 la->next = NULL;
 lb->next = NULL;
 node* p = L->next;
 node* rear = la;
 int t = 1;
 while (p != NULL) {
  node* temp = p->next;
  if (t % 2 == 1) {//采用尾插法
   p->next = rear->next;
   rear->next = p;
   rear = p;
  }
  else {//采用头插法
   p->next = lb->next;
   lb->next = p;
  }
  t++;
  p = temp;
 }
 display(la);
 display(lb);
}

7.在一个递增有序的线性表中,有数值相同的元素存在,若存储方式为单链表,设计算法去掉数值相同的元素,使表中不再有重复的元素

void delete_same(linklist& L) {
//在一个递增有序的线性表中,有数值相同的元素存在,若存储方式为单链表,
//设计算法去掉数值相同的元素,使表中不再有重复的元素
 node* pre = L->next;//指向大小相等的结点中的第一个结点
 if (pre == NULL) {
  return;
 }
 node* p = pre->next;
 while (p != NULL) {
  if (p->data == pre->data) {//说明中间有相同的元素
   p = p->next;
  }
  else {
   pre->next = p;
   pre = p;
   p = p->next;
  }
 }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值