怎么将两个顺序存储的有序表合并成一个有序表?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么将两个顺序存储的有序表合并成一个有序表?相关的知识,希望对你有一定的参考价值。

具体代码如下:

#include<stdio.h>

#include<stdlib.h>

#define MAX 40

typedef struct

int data[MAX];

int length;

LinkList;

void Initial_List(LinkList * &l,int n)//初始化顺序表

int i=0;

l=(LinkList *)malloc(sizeof(LinkList));

l->length = 0;

for(;i<n;i++)

scanf("%d",l->data+i);

l->length = n;

void Link(LinkList *l1,LinkList *l2,LinkList * &l3)//连接顺序表

int i,j;

l3=(LinkList *)malloc(sizeof(LinkList));

l3->length = l1->length + l2->length;

for(i=0;i<l3->length;i++)

if(i<l1->length)

l3->data[i] = l1->data[i];

else

l3->data[i] = l2->data[i%(l1->length)];

for(i=0;i<l3->length;i++)

for(j=i+1;j<l3->length;j++)

if(l3->data[i]>l3->data[j])

int temp=l3->data[i];

l3->data[i]=l3->data[j];

l3->data[j]=temp;

void Disp_List(LinkList *l)

int i=0;

printf("output:\\n");

for(;i<l->length;i++)

printf("%d ",l->data[i]);

printf("\\n");

int main()

LinkList *l1,*l2,*l3;

int n;

printf("请输入第一个序列的元素个数:\\n");

scanf("%d",&n);

printf("请输入第一个序列的所有元素:\\n");

Initial_List(l1,n);

printf("请输入第二个序列的元素个数:\\n");

scanf("%d",&n);

printf("请输入第二个序列的所有元素:\\n");

Initial_List(l2,n);

Link(l1,l2,l3);

Disp_List(l3);

return 0;

编写算法,将两个非递减有序顺序表A和B合成一个新的非递减有序顺序表C。

已知顺序表A和B的元素个数分别为m,n。其中顺序表采用动态分配内存空间,其定义如下:

typedef struct

ElemType *elem; //存储空间基址

int length;     //当前长度

int listsize;   //当前分配的存储容量

Sqlist;

*/

参考技术A 代码有错…还没法合并 参考技术B 具体代码如下:


#include<stdio.h>

 #include<stdlib.h>

  #define MAX 40
 
 
 
 typedef struct
 
 
 
 int data[MAX];
 
 int length;
 
 LinkList;
 
 
 
 void Initial_List(LinkList * &l,int n)//初始化顺序表
 
 
 
 int i=0;
 
 l=(LinkList *)malloc(sizeof(LinkList));
 
 l->length = 0;
 
 
 
 for(;i<n;i++)
 
 scanf("%d",l->data+i);
 
 l->length = n;
 
 
 
 
 
 void Link(LinkList *l1,LinkList *l2,LinkList * &l3)//连接顺序表
 
 
 
 int i,j;
 
 l3=(LinkList *)malloc(sizeof(LinkList));
 
 l3->length = l1->length + l2->length;
 
 
 
 for(i=0;i<l3->length;i++)
 
 
 
 if(i<l1->length)
 
 
 
 l3->data[i] = l1->data[i];
 
 
 
 else
 
 
 
 l3->data[i] = l2->data[i%(l1->length)];
 
 
 
 
 
 
 
 for(i=0;i<l3->length;i++)
 
 
 
 
 for(j=i+1;j<l3->length;j++)
 
 
 if(l3->data[i]>l3->data[j])
 
 
 
 int temp=l3->data[i];
 
 l3->data[i]=l3->data[j];
 
 l3->data[j]=temp;
 
 
 
 
 
 
 
 
 
 
 
 void Disp_List(LinkList *l)
 
 
 
 int i=0;
 
 printf("output:\\n");
 
 for(;i<l->length;i++)
 
 printf("%d ",l->data[i]);
 
 printf("\\n");
 
 
 
 
 
 int main()
 
 
 
 LinkList *l1,*l2,*l3;
 
 int n;
 
 
 
 printf("请输入第一个序列的元素个数:\\n");
 
 scanf("%d",&n);
 
 printf("请输入第一个序列的所有元素:\\n");
 
 Initial_List(l1,n);
 
 printf("请输入第二个序列的元素个数:\\n");
 
 scanf("%d",&n);
 
 printf("请输入第二个序列的所有元素:\\n");
 
 Initial_List(l2,n);
 
 
 
 Link(l1,l2,l3);
 
 Disp_List(l3);
 
 return 0;
 
 

合并排序——二路合并排序

  • 什么是合并排序

合并排序就是将两个或多个有序表合并成一个有序表,将两个有序表合并成一个有序表称为二路合并

  • 算法描述 :

二路合并排序的基本思想是:对于两个有序表合并,初始时, 把含有n个结点的待排序序列看作有n个长度为1的有序子表所组成,将它们依次两两合并,得到长度为2的若干有序子表,再对这些子表进行两两合并,一直重复到长度为n,排序完成。

  • 合并排序过程:

初始序列:

技术分享图片

 

二路合并排序需要较大的辅助空间,辅助空间的大小与待排序序列一样多。

(1)将14个原数据看成14个长度为1的有序表(只有一个数据,肯定是有序的)

(2)将14个有序表两两合并,即将1,2合并3,4合并.....如果后面有单独一个元素的,就单独放在那里,直接进入下一遍合并

技术分享图片

(3)经过第一遍的合并,得到长度为2的有序表序列,再将这些长度为2的有序表序列进行两两合并。

技术分享图片

(4)经过第二遍合并之后,得到长度为4的有序表的序列,再将这些长度为4的有序表进行两两合并。

技术分享图片

(5)  经过上面的合并,得到长度为8的有序表,再将这些长度为8的有序表进行两两合并。

 

技术分享图片

 

  • 合并相邻有序表 :

如果需合并的两个有序表分别保存于数组A中,其中一个序列保存在下标s~m的数组元素中,另一个序列保存在下标从m+1~n的数组元素中。合并把结果保存在数组R中。用变量i,j分别指向两个系列中需要比较的元素,变量k指向数组R中的序号,表示下一个要保存的数据的位置。

(1)  取第1个系列的第i个元素A[i],与第2个系列的第1个元素比较A[j]。

(2)  若A[i]<=A[j],则将A[i]复制到R[k]中,使i和k分别增加1.

(3)若A[i]>A[j],则将A[j]复制到R[k]中,使j和k分别增加1

(4)重复步骤1~3,直到一个序列复制完为止。

(5)将另一个序列中比较的数据复制到R的剩余位置。

//a[low...mid]a[mid+1,high]  b[low...high]

   void Merge(int a[],int b[],int low,int mid,int high){

      int i=low;

      int j=mid+1;

      int k=low;

     

      while(i<=mid && j<=high){

         if(a[i]<=a[j]){

            b[k++]=a[i++];

         }else{

            b[k++]=a[j++];

         }

      } private static void merge(int a[],int temp[],int low,int mid,int high){

   int i=low;

   int j=mid+1;

   int k=0;

  

   while(i<=mid && j<=high) {

      if(a[i]<=a[j]) {

         temp[k++]=a[i++];

      }else {

         temp[k++]=a[j++];

      }

   }

   while(i<=mid) {

      temp[k++]=a[i++];

   }

   while(j<=high) {

      temp[k++]=a[j++];

   }

   k = 0;

   // temp中的元素全部拷贝到原数组中

   while (low <= high) {

      a[low++] = temp[k++];

   }

}

 

  • 归并排序:

(1)  二路归并排序将a[low...high]中的记录归并排序后放入temp[low...high]中。当序列长度等于1时,递归结束,否则:

a)     将当前序列一分为二,求出分裂点mid=(low+high)/2

b)    对子序列a[low..mid]递归,进行归并排序,结果放入temp[low...mid]

c)     对子序列a[mid+1,high],进行归并排序,结果放入temp[mid+1,high]

d)    调用Merge将有序的两个子序列a[low..mid]与a[mid+1,high]归并为一个有序的序列temp[low...high]

/**

 * sort

 */

public static void sort(int a[],int temp[],int low,int high) {

   if(low<high) {

       int mid=(low+high)/2;

       sort(a,temp,low,mid);

       sort(a,temp,mid+1,high);

       merge(a,temp,low,mid,high);

   }

}

  • 算法实例:

public class MergeSort {

   /**

    * 相邻有序子序列进行合并

    *   a[low...mid] a[mid+1,high]

    */

   private static void merge(int a[],int temp[],int low,int mid,int high){

      int i=low;

      int j=mid+1;

      int k=0;

     

      while(i<=mid && j<=high) {

         if(a[i]<=a[j]) {

            temp[k++]=a[i++];

         }else {

            temp[k++]=a[j++];

         }

      }

      while(i<=mid) {

         temp[k++]=a[i++];

      }

      while(j<=high) {

         temp[k++]=a[j++];

      }

      k = 0;

      // temp中的元素全部拷贝到原数组中

      while (low <= high) {

         a[low++] = temp[k++];

      }

   }

  

   public static void sort(int a[],int temp[],int low,int high) {

      if(low<high) {

          int mid=(low+high)/2;

          sort(a,temp,low,mid);

          sort(a,temp,mid+1,high);

          merge(a,temp,low,mid,high);

      }

   }

   public static void sort(int []arr){

        int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间

        sort(arr,temp,0,arr.length-1);

    }

   public static void main(String[] args) {

      int arr[]= {56,41,26,32,55,75,2,63,12,19,58,77,34,95};

      sort(arr);

      System.out.println("排序结果:"+Arrays.toString(arr));

     

      /*

      测试,合并有序子序列

      int arr[]= {1,3,5,2,4,6};

      int temp[]=new int[arr.length];

      merge(arr, temp, 0, 2,   arr.length-1);

     

      System.out.println("排序结果:"+Arrays.toString(arr));

      System.out.println("排序结果:"+Arrays.toString(temp));

      */

   }

}



以上是关于怎么将两个顺序存储的有序表合并成一个有序表?的主要内容,如果未能解决你的问题,请参考以下文章

c语言实现两个顺序表的合并

两个递增有序表合并成一个递增有序表

两个递增有序表合并成一个递增有序表

两个有序单链表合并成一个有序单链表的java实现

Java实现两个递增有序链表合并成一个递增有序链表和两个非递减有序链表合成一个非递增有序链表

考研数据结构-顺序表(综合应用3)-合并顺序表