数据结构排序编程题汇总

本文详细介绍了多种排序算法的实现,包括直接插入排序、希尔排序等,并通过具体示例展示了算法的应用过程。此外,还提供了一种非递归的归并排序算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6-16 直接插入排序 (10分)

本题要求实现直接插入排序函数,待排序列的长度1<=n<=1000。

函数接口定义:

void  InsertSort(SqList L);

其中L是待排序表,使排序后的数据从小到大排列。 ###类型定义:

typedef  int  KeyType;
typedef  struct {                      
  KeyType *elem; /*elem[0]一般作哨兵或缓冲区*/                       
  int Length;      
}SqList;

裁判测试程序样例:

#include<stdio.h>
#include<stdlib.h>
typedef  int  KeyType;
typedef  struct {                      
  KeyType *elem; /*elem[0]一般作哨兵或缓冲区*/                       
  int Length;      
}SqList;
void  CreatSqList(SqList *L);/*待排序列建立,由裁判实现,细节不表*/ 
void  InsertSort(SqList L);
int main()
{
  SqList L;
  int i;
  CreatSqList(&L);
  InsertSort(L);
  for(i=1;i<=L.Length;i++)
   {        
      printf("%d ",L.elem[i]);
    }
  return 0;
}
/*你的代码将被嵌在这里 */

输入样例:
第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:

10
5 2 4 1 8 9 10 12 3 6

输出样例:
输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。

1 2 3 4 5 6 8 9 10 12 
/*将无序块首元素与左侧元素由后向前逐个比较,边比较边后移; 
最后定位到一个小于等于待插入元素的记录右侧,填入即可。*/
void  InsertSort(SqList L)
{
     int i,j; 
     for(i=2;i<=L.Length;++i)
     {
     	if(L.elem[i]<L.elem[i-1])
     	{
     		L.elem[0]=L.elem[i];//备份无序块首元素
            L.elem[i]=L.elem[i-1];
	        for(j=i-2;L.elem[j]>L.elem[0];--j)
			{
				L.elem[j+1]=L.elem[j]; //比首元素大的元素后移 
			}
			L.elem[j+1]=L.elem[0];//填入终止位置右侧		  
		 }
	 }
}

6-1 希尔排序的实现 (10分)

本题要求实现一趟希尔排序函数,待排序列的长度1<=n<=1000。

函数接口定义:

void  ShellInsert(SqList L,int dk);

其中L是待排序表,使排序后的数据从小到大排列。 ###类型定义:

typedef  int  KeyType;
typedef  struct {                      
  KeyType *elem; /*elem[0]一般作哨兵或缓冲区*/                       
  int Length;      
}SqList;

裁判测试程序样例:

#include<stdio.h>
#include<stdlib.h>
typedef  int  KeyType;
typedef  struct {                      
  KeyType *elem; /*elem[0]一般作哨兵或缓冲区*/                       
  int Length;      
}SqList;
void  CreatSqList(SqList *L);/*待排序列建立,由裁判实现,细节不表*/ 
void  ShellInsert(SqList L,int dk);
void  ShellSort(SqList L);

int main()
{
  SqList L;
  int i;
  CreatSqList(&L);
  ShellSort(L);
  for(i=1;i<=L.Length;i++)
   {        
     printf("%d ",L.elem[i]);
   }
  return 0;
}
void   ShellSort(SqList L)
{
  /*按增量序列dlta[0…t-1]对顺序表L作Shell排序,假设规定增量序列为5,3,1*/
   int k;
   int dlta[3]={5,3,1};
   int t=3;
   for(k=0;k<t;++k)
       ShellInsert(L,dlta[k]);
} 
/*你的代码将被嵌在这里 */

输入样例:
第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:

10
5 2 4 1 8 9 10 12 3 6

输出样例:
输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。

1 2 3 4 5 6 8 9 10 12 
void  ShellInsert(SqList L,int dk)
{
	int i,j;
	for(i=dk+1;i<=L.Length;i++)//从第dk+1个元素开始子序列内插入排序
	{
		if(L.elem[i]<L.elem[i-dk])//子序列内前一个不再是i-1,而是i-dk
		{
			L.elem[0]=L.elem[i];
            L.elem[i]=L.elem[i-dk];
			for(j=i-dk;L.elem[j]>L.elem[0]&&j>0;j-=dk)//子序列后移dk位 
			{
				L.elem[j+dk]=L.elem[j];
			}
			L.elem[j+dk]=L.elem[0];
		}
	 } 
	
} 

7-2 人以群分 (25分)

社交网络中我们给每个人定义了一个“活跃度”,现希望根据这个指标把人群分为两大类,即外向型(outgoing,即活跃度高的)和内向型(introverted,即活跃度低的)。要求两类人群的规模尽可能接近,而他们的总活跃度差距尽可能拉开。

输入格式:
输入第一行给出一个正整数N(2≤N≤10​5​​ )。随后一行给出N个正整数,分别是每个人的活跃度,其间以空格分隔。题目保证这些数字以及它们的和都不会超过2^​31。

输出格式:
按下列格式输出:

Outgoing #: N1
Introverted #: N2
Diff = N3

其中N1是外向型人的个数;N2是内向型人的个数;N3是两群人总活跃度之差的绝对值。

输入样例1:

10
23 8 10 99 46 2333 46 1 666 555

输出样例1:

Outgoing #: 5
Introverted #: 5
Diff = 3611

输入样例2:

13
110 79 218 69 3721 100 29 135 2 6 13 5188 85

输出样例2:

Outgoing #: 7
Introverted #: 6
Diff = 9359
//要求两类人群的规模尽可能接近,而他们的总活跃度差距尽可能拉开。
//如果输入的n为奇数个,那么多的那一个人一定是放到外向的人数里面,来使大的更大 
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include <algorithm>
using namespace std; 

int main()
{
  int i,n;
  scanf("%d",&n);
  int a[100000];
  for(i=1;i<=n;i++)
  {
  	scanf("%d",&a[i]);
  }
  sort(a+1,a+n+1);
   int n1=0,n2=0,n3=0;
   int outsum=0;//外向型总活跃度
   int insum=0;//内向型总活跃度
   int out[50000];
   int in[50000];
   int outp;//外向型人数 
   outp=(n%2==0 ? n/2 : n/2+1); 
   int inp=n-outp;//内向型人数 
   for(i=1;i<=inp;i++)
   {
   		in[i]=a[i];
   	//	printf("%d ",in[i]); 
   		insum+=in[i];
   }
  // printf("\n");
   for(i=1;i<=outp;i++)
   {
   	    out[i]=a[i+inp];
   	//    printf("%d ",out[i]); 
   	    outsum+=out[i];
   }
  // printf("\n");
   n1=outp;
   n2=inp;
   n3=outsum-insum;
   printf("Outgoing #: %d\n",n1);
   printf("Introverted #: %d\n",n2);
   printf("Diff = %d\n",n3);
  return 0;
}

7-1 排序 (25分)

给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。

本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:

数据1:只有1个元素;
数据2:11个不相同的整数,测试基本正确性;
数据3:103个随机整数;
数据4:104个随机整数;
数据5:105个随机整数;
数据6:105个顺序整数;
数据7:105个逆序整数;
数据8:105个基本有序的整数;
数据9:105个随机正整数,每个数字不超过1000。
加粗样式输入格式:
输入第一行给出正整数N(≤10^​5),随后一行给出N个(长整型范围内的)整数,其间以空格分隔。

输出格式:
在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。

输入样例:

11
4 981 10 -17 0 -20 29 50 8 43 -5

输出样例:

-20 -17 -5 0 4 8 10 29 43 50 981
//heapsort
#include<stdio.h>
#include<stdlib.h>
typedef  int  KeyType;
typedef  struct {                      
  KeyType *elem;/*elem[0]一般作哨兵或缓冲区*/                 
  int Length;      
}SqList;
void  CreatSqList(SqList &H);/*待排序列建立*/ 
void HeapAdjust(SqList &H,int head ,int tail);
void HeapSort(SqList &H);
int main()
{
  SqList H;
  int i;
  CreatSqList(H);
  HeapSort(H);
  printf("%d",H.elem[1]);
  for(i=2;i<=H.Length;i++)
   {        
     printf(" %d",H.elem[i]);
   }
   printf("\n");
 
  return 0;
}
void  CreatSqList(SqList &H)
{
	int i,n;
	scanf("%d",&n);
	if(n<=0) return;
	else
	{
		H.elem=(KeyType*)malloc(sizeof(KeyType)*n);
		H.Length=0;
		for(i=1;i<=n;i++) //0号作为哨兵 
		{
			scanf("%d",&H.elem[i]);
			H.Length++;
		}
	}
}  
void HeapAdjust(SqList &H,int head ,int tail)
{
	//H内存中是顺序表,逻辑上是二叉树、堆 
	int rc=H.elem[head];
	int lchild=2*head;
	int rchild=2*head+1;
	int gchild;//大孩子 
	while(lchild<=tail)//只要左孩子存在 
	{
		if(rchild<=tail&&H.elem[lchild]<H.elem[rchild])
		gchild=rchild;
		else gchild=lchild;
		if(rc<H.elem[gchild])
		{
			H.elem[head]=H.elem[gchild];
			head=gchild;
			lchild=2*head;
			rchild=2*head+1;
		}
		else break;				
	}  
	H.elem[head]=rc;
}
void HeapSort(SqList &H)
{
	int i;
	for(i=H.Length/2;i>0;--i)
	{
		HeapAdjust(H,i,H.Length);
	}
	for(i=1;i<=H.Length-1;i++)
	{
		int t=H.elem[1];
		H.elem[1]=H.elem[H.Length-i+1];
		H.elem[H.Length-i+1] = t;
		HeapAdjust(H,1,H.Length-i);
	} 
}
//shellsort
//#include<stdio.h>
//#include<stdlib.h>
//typedef  int  KeyType;
//typedef  struct {                      
//  KeyType *elem; /*elem[0]一般作哨兵或缓冲区*/                       
//  int Length;      
//}SqList;
//void  CreatSqList(SqList *L);/*待排序列建立*/ 
//void  ShellInsert(SqList L,int dk);
//void  ShellSort(SqList L);
//
//int main()
//{
//  SqList L;
//  int i;
//  CreatSqList(&L);
//  ShellSort(L);
//  printf("%d",L.elem[1]);
//  for(i=2;i<=L.Length;i++)
//   {        
//     printf(" %d",L.elem[i]);
//   }
//   printf("\n");
// 
//  return 0;
//}
//void  CreatSqList(SqList *L)
//{
//	int i,n;
//	scanf("%d",&n);
//	if(n<=0) return;
//	else
//	{
//		L->elem=(KeyType*)malloc(sizeof(KeyType)*n);
//		L->Length=0;
//		for(i=1;i<=n;i++)//0号作为哨兵 
//		{
//			scanf("%d",&L->elem[i]);
//			L->Length++;
//		}
//	}
//} 
//void   ShellSort(SqList L)
//{
//  /*按增量序列dlta[0…t-1]对顺序表L作Shell排序,假设规定增量序列为5,3,1*/
//   int k;
//   int dlta[3]={5,3,1};
//   int t=3;
//   for(k=0;k<t;++k)
//       ShellInsert(L,dlta[k]);
//} 
//void  ShellInsert(SqList L,int dk)
//{
//	int i,j;
//	for(i=dk+1;i<=L.Length;i++)
//	{
//		if(*(L.elem+i)<*(L.elem+i-dk))
//		{
//			*(L.elem)=*(L.elem+i);//备份无序子序列首元素
//			for(j=i-dk;j>0&&*(L.elem+j)>*(L.elem);j-=dk)
//			{
//				*(L.elem+j+dk)=*(L.elem+j);
//			 } 
//			 *(L.elem+j+dk)=*(L.elem);
//		}
//	}
//}



//sort
//#include<stdio.h>
//#include<stdlib.h>
//#include<iostream>
//#include <algorithm>
//using namespace std; 
//
//int main()
//{
//  int i,n;
//  scanf("%d",&n);
//  int a[100000];
//  for(i=1;i<=n;i++)
//  {
//  	scanf("%d",&a[i]);
//  }
//  sort(a+1,a+n+1);
//    printf("%d",a[1]);
//  for(i=2;i<=n;i++)
//   {        
//     printf(" %d",a[i]);
//   }
//   printf("\n");
//  return 0;
//}


//quicksort
#include<stdio.h>
#include<stdlib.h>
typedef  int  KeyType;
typedef  struct {                      
  KeyType *elem;/*elem[0]一般作哨兵或缓冲区*/                 
  int Length;      
}SqList;
void  CreatSqList(SqList *L);/*待排序列建立*/ 
int Partition(SqList L,int low,int high);
void QSort(SqList L,int low,int high);

int main()
{
  SqList L;
  int i;
  CreatSqList(&L);
  QSort(L,1,L.Length);
  printf("%d",L.elem[1]);
  for(i=2;i<=L.Length;i++)
   {        
     printf(" %d",L.elem[i]);
   }
   printf("\n");
 
  return 0;
}
void  CreatSqList(SqList *L)
{
	int i,n;
	scanf("%d",&n);
	if(n<=0) return;
	else
	{
		L->elem=(KeyType*)malloc(sizeof(KeyType)*n);
		L->Length=0;
		for(i=1;i<=n;i++) //0号作为哨兵 
		{
			scanf("%d",&L->elem[i]);
			L->Length++;
		}
	}
} 
int Partition(SqList L,int low,int high)
{
	L.elem[0]=L.elem[low];
	while(low<high)
	{
		while(high>low&&L.elem[high]>=L.elem[0])
		--high;//high左移 
		L.elem[low]=L.elem[high];
		while(low<high&&L.elem[low]<=L.elem[0])
		++low;
		L.elem[high]=L.elem[low];
	}
	L.elem[low]=L.elem[0];
	return low;
} 
void QSort(SqList L,int low,int high)
{
	if(!(low<high)) return;
	else
	{
		int pivotloc=Partition(L,low,high);
		QSort(L,low,pivotloc-1);
		QSort(L,pivotloc+1,high);
	}
}

7-2 寻找大富翁 (25分)

胡润研究院的调查显示,截至2017年底,中国个人资产超过1亿元的高净值人群达15万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。

输入格式:
输入首先给出两个正整数N(≤10^​6)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。

输出格式:
在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。

输入样例:

8 3
8 12 7 3 20 9 5 18

输出样例:

20 18 12
#include<stdio.h>
#include<stdlib.h>
typedef  int  KeyType;
typedef  struct {                      
  KeyType *elem;/*elem[0]一般作哨兵或缓冲区*/                 
  int Length;      
}SqList;
void  CreatSqList(SqList &H);/*待排序列建立*/ 
void HeapAdjust(SqList &H,int head ,int tail);
void HeapSort(SqList &H);
int main()
{
  SqList H;
  int i;
    int n;
	scanf("%d",&n);
	 int m;
    scanf("%d",&m);
	if(n<=0) printf("error");
	else
	{
		H.elem=(KeyType*)malloc(sizeof(KeyType)*n);
		H.Length=0;
		for(i=1;i<=n;i++)//0号作为哨兵 
		{
			scanf("%d",&H.elem[i]);
			H.Length++;
		}
	} 
  HeapSort(H);
  if(m>n)
  {
      printf("%d",H.elem[1]);
  	for(i=2;i<=n;i++)
  	   printf(" %d",H.elem[i]);
  }
  else
	{
	    printf("%d",H.elem[1]);
	  for(i=2;i<=m;i++)
	   {        
	     printf(" %d",H.elem[i]);
	   }
    }
   printf("\n");
 
  return 0;
}
void HeapAdjust(SqList &H,int head ,int tail)
{
	//H内存中是顺序表,逻辑上是二叉树、堆 
	int rc=H.elem[head];
	int lchild=2*head;
	int rchild=2*head+1;
	int gchild;//大孩子 (非递增排序时大孩子数值小) 
	while(lchild<=tail)//只要左孩子存在 
	{
		if(rchild<=tail&&H.elem[lchild]>H.elem[rchild])
		gchild=rchild;
		else gchild=lchild;
		if(rc>H.elem[gchild])
		{
			H.elem[head]=H.elem[gchild]; 
			head=gchild;
			lchild=2*head;
			rchild=2*head+1;
		}
		else break;				
	}  
	H.elem[head]=rc;
}
void HeapSort(SqList &H)
{
	int i;
	for(i=H.Length/2;i>0;--i)
	{
		HeapAdjust(H,i,H.Length);
	}
	for(i=1;i<=H.Length-1;i++)
	{
		int t=H.elem[1];
		H.elem[1]=H.elem[H.Length-i+1];
		H.elem[H.Length-i+1] = t;
		HeapAdjust(H,1,H.Length-i);
	} 
}

6-1 Iterative Mergesort (25分)

How would you implement mergesort without using recursion?

The idea of iterative mergesort is to start from N sorted sublists of length 1, and each time to merge a pair of adjacent sublists until one sorted list is obtained. You are supposed to implement the key function of merging.

Format of functions:

void merge_pass( ElementType list[], ElementType sorted[], int N, int length );

The function merge_pass performs one pass of the merge sort that merges adjacent pairs of sublists from list into sorted. N is the number of elements in the list and length is the length of the sublists.

Sample program of judge:

#include <stdio.h>

#define ElementType int
#define MAXN 100

void merge_pass( ElementType list[], ElementType sorted[], int N, int length );

void output( ElementType list[], int N )
{
    int i;
    for (i=0; i<N; i++) printf("%d ", list[i]);
    printf("\n");
}

void  merge_sort( ElementType list[],  int N )
{
    ElementType extra[MAXN];  /* the extra space required */
    int  length = 1;  /* current length of sublist being merged */
    while( length < N ) { 
        merge_pass( list, extra, N, length ); /* merge list into extra */
        output( extra, N );
        length *= 2;
        merge_pass( extra, list, N, length ); /* merge extra back to list */
        output( list, N );
        length *= 2;
    }
} 


int main()
{
    int N, i;
    ElementType A[MAXN];

    scanf("%d", &N);
    for (i=0; i<N; i++) scanf("%d", &A[i]);
    merge_sort(A, N);
    output(A, N);

    return 0;
}

/* Your function will be put here */

Sample Input:

10
8 7 9 2 3 5 1 6 4 0

Sample Output:

7 8 2 9 3 5 1 6 0 4 
2 7 8 9 1 3 5 6 0 4 
1 2 3 5 6 7 8 9 0 4 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
void merge_pass( ElementType list[], ElementType sorted[], int N, int length )
{
  	   int *a=list;
      int *b=sorted;
      int t=0;
	  int pos=0; 
     while(pos<N)
       {
       	  int left=pos;
       	  int right=pos+length;
       	  while(left<pos+length&&right<pos+length+length&&left<N&&right<N)
       	  {
       	  	if(a[left]<a[right])
				 {
				 	b[t++]=a[left++];
				  } 
		    else
			{
				b[t++]=a[right++];
						  
			}  
		 }
			while(left<pos+length&&left<N)//合并剩余元素 
			{
				b[t++]=a[left++];
			}
			while(right<pos+2*length&&right<N)
			{
				b[t++]=a[right++];
			}	
	      pos+=2*length;
      }
  }

7-2 链式基数排序 (20分)

实现链式基数排序,待排序关键字n满足1≤n≤1000,最大关键字数位≤5。

输入样例:
第一行输入待排序个数n(1≤n≤1000),再输入n个数(n的数位≤5)。

10
278 109 63 930 589 184 505 269 8 83

输出样例:
输出每趟分配-收集后链表中的关键字,趟数为序列中最大值的数位(如样例中930的数位为3),每行结尾有空格。

930 63 83 184 505 278 8 109 589 269 
505 8 109 930 63 269 278 83 184 589 
8 63 83 109 184 269 278 505 589 930 
#include<iostream>
#include<malloc.h>
using namespace std;
//链式队列的节点结构,模拟桶
struct Node
{
	int data;//数据域
	Node *next;//指针域
};
//定义程序所需的特殊队列
class Queue
{
private:
	Node *front;//链式对列的头指针
	Node *rear;//链队的尾指针
public:
	//构造函数,初始化队列(带头结点的链式队列)
	Queue()
	{
		//开始先构造一个空结点,没有数据元素存储
		Node *p = new Node;
		p->data = 0;
		p->next = NULL;
		//开始是空链队,首尾指针分别去指向队头结点
		front = p;
		rear = p;
	}
	//析构函数,销毁链队的结点占据的内存
	~Queue()
	{
		Node *p = front;
		Node *q;
		while (p != NULL)
		{
			q = p;
			p = p->next;
			delete q;
		}
	}
	//入队函数,从尾进入,节点不存在,需要自行创建结点
	void push(int e)
	{
		Node *p = new Node;
		p->data = e;
		p->next = NULL;
		rear->next = p;
		rear = p;
	}
	//入队函数重载,尾进入,节点原来就存在的函数,不需要再新建结点和存储结点的内容
	void push(Node *p)
	{
		p->next = NULL;
		rear->next = p;
		rear = p;
	}
	//求数据元素的最大位数的函数,也就是求出需要分配和收集的次数
	int lengthData()
	{
		int length = 0;
		int n = 0; 
		int d;
		//指示指针
		Node *p = front->next;
		//遍历
		while (p != NULL)
		{
			d = p->data;
			while (d > 0)
			{
				d /= 10;
				n++;
			}
			p = p->next;
			if (length < n)
			{
				length = n;
			}
			n = 0;
		}
		return length;
	}
	//判断队列是否为空
	bool empty()
	{
		if (front == rear)
		{
			return true;
		}
		return false;
	}
	//清除队列中的元素
	void clear()
	{
		front->next = NULL;
		rear = front;
	}
	//输出队列中的元素
	void print(Queue &que)
	{
		Node *p = que.front->next;
		while (p != NULL)
		{
			cout << p->data << " ";
			p = p->next;
		}
	}
	//基数排序过程
	void RadixSort(Queue& que)
	{
		Queue *arr[10];
		for (int i = 0; i < 10; i++)
		{
			arr[i] = new Queue;
		}
		int maxLen = que.lengthData();
		int d = 1;
		for (int i = 0; i < maxLen; i++)
		{
			Node *p = que.front->next;
			Node *q;
			int k;
			while (p != NULL)
			{
				k = (p->data / d) % 10;
				q = p->next;
				arr[k]->push(p);
				p = q;
			}
			que.clear();
			for (int i = 0; i < 10; i++)
			{
				if (!arr[i]->empty())
				{
					Node *p = arr[i]->front->next;
					Node *q;
					while (p != NULL)
					{
						q = p->next;
						que.push(p);
						p = q;
					}
				}
			}
			for (int i = 0; i < 10; i++)
			{
				arr[i]->clear();
			}
			d *= 10;
			//输出每一趟队列中排好序的元素
			print(que);
			cout<<endl;
		}
	}
};

int main(void)
{
	Queue queue;
	int i,n;
     cin>>n;
	//顺序输入元素
	while (n>0)
	{
		cin>>i;
		queue.push(i);
		n--;
	}
	//基数排序
	queue.RadixSort(queue);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值