数据结构与算法--逆置

目录

一.顺序表的逆置

1.设计一个高效的算法,将顺序表L中的所有元素逆置

思想:

代码:

2.已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,...am)和(b1,b2,...bn)尝试编写一个函数将数组中两个顺序表的位置互换,即将(b1,b2,...bn)放在(a1,a2...am)的前面

思想:

代码:

3.带头结点的单链表从尾到头反向输出

方法一:尾插法实现反向输出

方法二:栈来实现

思想:

方法三:递归来实现

思想:

代码:

4.带头结点的单链表就地逆置

方法一:头插法建立单链表

思想:

代码:

方法二.指针反转

思想:

代码:

5.利用栈和队列实现队列中元素逆置(Q是一个队列,S是一个空栈)

思想:

代码:


一.顺序表的逆置

1.设计一个高效的算法,将顺序表L中的所有元素逆置

思想:

    扫描顺序表L的前半部分元素,对于元素L.data[i](0<=i<L.length/2)

    将其与后半部分对应元素L.data[L.length-i-1]进行交换    

代码:

​
​
void Reverse(SqList &L)
{
  int temp;//辅助变量
  for(i=0;i<L.length/2;i++)
  {
    temp=L.data[i];//交换
    L.data[i]=L.data[L.length-1];
    L.data[length-i-1]=temp;
  }
}

2.已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,...am)和(b1,b2,...bn)尝试编写一个函数将数组中两个顺序表的位置互换,即将(b1,b2,...bn)放在(a1,a2...am)的前面

思想:

(1)先将数组A[m+n]的全部元素原地逆置为(bn,bn-1,...........b1,am,am-1,.......a1)

(2)再对前n 个元素和后m个元素分别使用逆置算法,即可得到(b1,...bn,a1,....an)

代码:

void Reverse(int A[],int left,int right ,int arraysize)
{ //left和right 对应数组下标,arraysize 为数组的长度
  if(left>=right||right>=arraysize)
     return ;//返回为空
  int mid=(left+right)/2;
  for(int i=0;i<mid-left;i++)
  {
    int temp=A[left+i];
    A[left+i]=A[right-i];
    A[right-i]=temp;
  }
}
void Exchange(int A[],int m,int n,int arraysize)
{
  /*数组A[m+n]中,从0到m-1存放顺序表(a1,a2,...am),从m到m+n-1存放顺序表(b1,b2,...bn)算法将这两个表的位置互换 */
  Reverse(A,0,m+n-1,arraysize);//整个表逆置
  Reverse(A,0,n-1,arraysize);//前n个元素逆置
  Reverse(A,n,m+n-1,arraysize);//后m个元素逆置
}

3.带头结点的单链表从尾到头反向输出

方法一:尾插法实现反向输出

方法二:栈来实现

思想:

每经过一个结点,将该结点放入栈中,遍历完整个链表,再从栈顶开始输出结点值

方法三:递归来实现

思想:

每当访问一个结点是,先递归输出它后面的结点,再输出该结点本身,这样链表就反向输出

代码:

void R_print(Linklist L)
{
  //从尾到头输出单链表中每个结点的值
  if(L->next!=NULL)
  {
    R_print(L->next);//递归输出后面的结点
  }
  if(L!=NULL)
    print(L->data);//找到最后面的结点就输出对应的data值
}

4.带头结点的单链表就地逆置

方法一:头插法建立单链表

思想:

将头结点摘下,然后从第一结点开始,依次插入到头结点的后面(头插法建立单链表),直到最后一个结点为止,这样就实现了链表的逆置。

代码:

LinkList Reverse_1(LinkList L)
{
  LNode*p,*r;//p为工作指针,r为p的后继,以防断链
  p=L->next;//从第一个元素结点开始
  L->next=NULL;//先将头结点的next域置位NULL
  while(P!=NULL)//依次将元素结点摘下
  {
    r=p->next;//用r暂存p的后继,以防断链
    p->next=L->next;//将p结点插入到头结点之后
  }
}

方法二.指针反转

思想:

用pre,p,r分别指向三个结点,分别为当前结点的前一个结点,当前结点,当前结点的后一个结点。依次往后面遍历,改变指针的指向,到最后一个结点时,插到头结点的后面

代码:

LinkList Reverse_2(LinkList L)
{
  //依次遍历线性表L,并将结点指针反转
  LNode*pre,*p=L->next,*r=p->next;//分别用pre,p,r来表示连续的三个结点
  p->next=NULL;//处理第一个结点,将第一个结点指针指向NULL。就表示放到链表的尾部
  while(r!=NULL)
  {
    pre=p;//从第二个结点开始依次继续遍历,三个结点往后面移
    p=r;
    r=r->next;
    p->next=pre;//指针反转,第一个反转的是第二个结点指向第一个结点
  }
  L->next=p;//处理最后一个结点,将最后一个结点放到头结点的后面
  return L;
}

5.利用栈和队列实现队列中元素逆置(Q是一个队列,S是一个空栈)

思想:

队列中元素全部出队列再进栈,然后再出栈进队列 

代码:

void Inserver(Stack S,Queue Q)
{
  while(!QueueEmpty(Q))
  {
  //若队列不为空
   x=Dequeue(Q);//队列中元素全部出队
   Push(S,x);//队列中全部元素依次进栈
  }
  while(StackEmpty(S))
  {
    //若栈不为空
    Pop(S,x);//栈中元素全部出栈
    Enqueue(Q);//栈中元素全部入队列
  }
}

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值