排序
思路:
直接做一次排序 然后特判一下即可
需要注意輸出格式是在每個數前輸出空格
排序推薦直接使用c++的sort函數
需要下面這兩句引入
#include <algorithm>
using namespace std;
代碼:
#include "stdio.h"
#include <algorithm>
using namespace std;
int main(){
int a[1005],b[1005], n, i, j, k, m, t, aver=0;
FILE *fp;
if((fp=fopen("sort.in", "r")) != NULL ){
fclose(fp); //存在的話,要先把之前打開的文件關掉
freopen("sort.in", "r", stdin);
//freopen("sort.out", "w", stdout);
}
scanf("%d", &n);
for( i=0; i<n; i++){
scanf("%d", &a[i]);
aver += a[i];
}
aver = (int)(1.0*aver/n + 0.5) ;
//********************************************************
//為a數組從小到大排序
sort(a,a + n);
k = 0;//記錄到哪個位置 大於平均數
for(i = 0; i < n; i++){
if(a[i] <= aver){
printf(" %d",a[i]);
}
else { //此時大於平均數 要逆序輸出
k = i;
break;
}
}
//開始逆序輸出
for(i = n-1;i >= k;i--){
printf(" %d",a[i]);
}
//========================================================
return 0;
}
哈夫曼樹(比較難)
思路:
最麻煩的地方在於構建數結構 哈夫曼的思維是每次取列表中兩個值最小的合並 合並后的值加入列表
通過使用優先隊列的小根堆結構 可以比較方便的實現
使用pair結構保存節點的值和節點的下標
優先隊列會默認按照pair的first值排序 省去一部分代碼
樹結構創建好后 就很簡單了 從根節點遍歷遞歸即可
代碼:
#include "stdio.h"
#include <queue>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
priority_queue<PII,vector<PII>,greater<PII> >q; //小根堆
const int N0=1000;
const int inf=10000000;
struct node1{
int w, lch, rch, parent;
}ht[2*N0];
int n=0, root, WPL=0;
void readData(){
int i;
int num[256]={ 0 };
char ch;
while( (ch=getchar())!=EOF ){
num[ch]++;
}
for( i=0; i<=255; i++ ){
if( num[i] ){
n++;
ht[n].w=num[i];
}
}
root=2*n-1;
}
//********************************************************
void create_ht(){
int i;
for(i = 1;i <= n;i++){
PII p = {ht[i].w,i};
q.push(p);
}
//每次從優先隊列中取兩個最小值出來
while(!q.empty() && q.size() > 1){
auto q1 = q.top();
q.pop();
auto q2 = q.top();
q.pop();
n++;
ht[n].w = q1.x + q2.x; //構建節點並添加到優先隊列中
ht[n].lch = q1.y;
ht[n].rch = q2.y;
q.push({ht[n].w,n});
}
root = n;
}
//========================================================
void doWPL( int root, int high ){
//********************************************************
if(ht[root].lch ==0 && ht[root].rch == 0){ //沒有左兒子以及右兒子 說明遞歸到底部 根據公式計算值
WPL += ht[root].w * (high - 1); //計算值
return ;
}
if(ht[root].lch != 0){ //如果有左兒子
doWPL(ht[root].lch,high + 1);
}
if(ht[root].rch != 0){ //如果有右兒子
doWPL(ht[root].rch,high + 1);
}
//========================================================
}
int main(){
FILE *fp;
if((fp=fopen("huffman.in", "r")) != NULL ){
fclose(fp); //存在的話,要先把之前打開的文件關掉
freopen("huffman.in", "r", stdin);
//freopen("huffman.out", "w", stdout);
}
readData();
create_ht();
doWPL( root, 1 );
printf("%d\n", WPL);
return 0;
}
最短距離
思路:
Dijkstra算法步驟:
- 定義一個dist距離數組 dist[起點] = 0 ,dist[其他點] 全部初始化為 INF
- 循環n-1次 每次找未使用的距離最近的點(和1號點的距離) 用該點去更新他能去的邊的距離 即更新dist數組的值
由於我們要記錄使用狀態 需要一個額外數組記錄使用狀態 (做完才發現給了used數組 ==)
代碼:
#include "stdio.h"
#include<iostream>
#include<algorithm>
#define maxint 10000
using namespace std;
int n,used[31],map[31][31];
bool st[31];
int dist[50]; // dist[n] = 起點到點 n 的最短距離
void ini( ){
int i,j;
scanf("%d", &n);
for( i=1; i<=n; i++){
for( j=1; j<=n; j++){
scanf("%d", &map[i][j]);
if( map[i][j] == 0 ){
map[i][j]=maxint;
}
}
}
}
void Dijkstra(){
//********************************************************
for(int i = 0;i < 50 ;i++){
dist[i] = maxint; //其他距離都初始化為理論上的無窮大
}
dist[1] = 0; //起點到起點的距離為0
int i,j;
for(i = 0;i < n - 1;i++){ //遍歷 n-1次
int t = -1;
for(j = 1;j <= n;j++){
//每次找未使用的距離最近的點
if(!st[j] && (t == -1 || dist[t] > dist[j])){
t = j;
}
}
// 根據該點去更新他能去的邊的距離
for(j = 1;j <= n;j++){
//如果是不可達到的點
//map[t][j] 為 maxint 便不會更新dist[j]的值
dist[j]=min(dist[j],dist[t] + map[t][j]);
}
//使用該點后記錄狀態為被使用
st[t] = true;
}
printf("%d",dist[n]); //根據dist數組的含義 直接輸出dist[n]即可
//========================================================
}
int main(){
FILE *fp;
if((fp=fopen("dist.in", "r")) != NULL ){
fclose(fp); //存在的話,要先把之前打開的文件關掉
freopen("dist.in", "r", stdin);
//freopen("dist.out", "w", stdout);
}
ini();
Dijkstra();
return 0;
}
路徑回溯
思路:
這種回溯問題 大部分都可以通過棧來保存 然后輸出棧即可(做到了逆序輸出)
代碼:
#include "stdio.h"
#include <stack>
using namespace std;
int n, pre[26][2];
char station[26]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
void ini(){
int i;
scanf("%d", &n);
for(i=0; i<n; i++){
scanf("%d%d", &pre[i][0], &pre[i][1]);
}
}
void Pathway(){
//********************************************************
stack<int>s; //定義一個棧
int i;
//由於題目A必是起點 所以直接從B開始循環 即 i = 1開始
for(i = 1;i < n;i++){
int distance = 0; //距離
int x = i;
while(x != 0){ //根據pre數組循環到起點A 並通過棧保存中間的路徑
distance += pre[x][1];
s.push(x);
x = pre[x][0];
}
//輸出路徑 起點必是A 我們直接輸出
printf("A");
while(!s.empty()){
int temp = s.top();
s.pop();
printf("-%c",station[temp]);
}
//路徑輸出完畢輸出距離
printf(" %d\n",distance);
}
//========================================================
}
int main(){
FILE *fp;
if((fp=fopen("DictS.in", "r")) != NULL ){
fclose(fp); //存在的話,要先把之前打開的文件關掉
freopen("DictS.in", "r", stdin);
//freopen("DictS.out", "w", stdout);
}
ini();
Pathway();
return 0;
}
數據庫查詢
思路:
說白了就是結構體排序 直接為sort自定義排序規則即可實現
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define SIZE 100
int n;
struct Grade_table{
int no_stu; /* the number of student*/
char name[20]; /* the name of student*/
int maths;
int english;
int computer;
};
struct Grade_table grade[SIZE];
//自定義排序規則
bool cmp(Grade_table &a,Grade_table &b){
//按照學號從小到大排序 即使用 <
return a.no_stu < b.no_stu;
}
void ini( ){
int i;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d %s %d %d %d",&(grade[i].no_stu),grade[i].name,&(grade[i].maths),&(grade[i].english),&(grade[i].computer));
}
}
void select2(){
//********************************************************
sort(grade,grade + n,cmp);
//遍歷輸出即可
int i;
for(i = 0;i < n;i++){
if(grade[i].computer >= 60 && grade[i].english >= 60 && grade[i].maths >= 60){
printf("%d,%s,%d,%d,%d\n",grade[i].no_stu,grade[i].name,grade[i].maths,grade[i].english,grade[i].computer);
}
}
//========================================================
}
int main(){
FILE *fp;
if((fp=fopen("DB.in", "r")) != NULL ){
fclose(fp); //存在的話,要先把之前打開的文件關掉
freopen("DB.in", "r", stdin);
//freopen("DB.out", "w", stdout);
}
ini();
select2();
return 0;
}
模擬進程調度算法
思路:
還是一題結構體排序問題 只是稍微復雜了點
根據題意我們優先根據進程到達時間從小到大排序
如果兩者時間相同時根據運行時間從小到大排序
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
struct Job_type{
int no; //作業號
int tb; //作業開始時間(分)
int tr; //運行時間(分)
}x;
Job_type job[36];
int n;
bool cmp(Job_type &a,Job_type &b){
if(a.tb != b.tb){ //如果時間不同就按照時間排序
return a.tb < b.tb;
}
else { //否則按照運行時間排序
return a.tr < b.tr;
}
}
void load(){
int i,j;
scanf("%d", &n);
for( i=0; i<n; i++){
scanf("%d", &job[i].no);
scanf("%d", &job[i].tb);
scanf("%d", &job[i].tr);
}
printf("輸入作業順序:\n");
for(i=0;i<n;i++){
printf("\t%d\t%d\t%d\n",job[i].no,job[i].tb,job[i].tr);
}
}
void fcfs_sjf(){
//********************************************************
sort(job,job + n,cmp); //直接進行一個序的排
//========================================================
printf("FCFSsjf調度結果:\n");
printf(" 開始時間 作業號 到達時間 運行時間 完成時間 等待時間 周轉時間\n");
//********************************************************
//遍歷輸出即可
int i;
int time = 0; //記錄當前時間
for(i = 0;i < n;i++){
Job_type t = job[i]; //節省代碼量。
//周轉時間 等於 完成時間 - 到達時間
printf("\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",time,t.no,t.tb,t.tr,time + t.tr,time - t.tb,time + t.tr - t.tb);
// 當前時間 加上該進程運行時間
time += t.tr;
}
//========================================================
}
int main(){
FILE *fp;
if((fp=fopen("os.in", "r")) != NULL ){
fclose(fp); //存在的話,要先把之前打開的文件關掉
freopen("os.in", "r", stdin);
//freopen("os.out", "w", stdout);
}
load();
fcfs_sjf();
return 0;
}
平均分
思路:
輸入沒有給數據長度 我們需要做循環讀取操作
同時題目要求保留整數部分即可 所以不用做四舍五入的特殊操作
代碼:
#include <stdio.h>
void average(){
//********************************************************
int i,j,k;
int len = 0; //記錄長度
int sum = 0; //記錄總和
int aver = 0; //平均值
while(scanf("%d",&i) != EOF){ //循環讀取數據 直到文件末尾
sum += i;
if(i > 100 || i < 0){
aver = -1;
break;
}
len++;
}
if(aver != -1){
aver = sum / len;
}
printf("%d",aver);
//========================================================
}
int main(){
FILE *fp;
if((fp=fopen("average.in", "r")) != NULL ){
fclose(fp); //存在的話,要先把之前打開的文件關掉
freopen("average.in", "r", stdin);
//freopen("average.out", "w", stdout);
}
average();
return 0;
}
字典回溯
思路:
和上面那題回溯完全一致 用棧即可。。
#include "stdio.h"
#include <stack>
using namespace std;
struct dictionary{
int index;
char last_char;
}dict[36];
int n;
void ini(){
int i;
scanf("%d", &n);
for(i=0; i<n; i++){
scanf("%d %c", &dict[i].index, &dict[i].last_char);
}
}
void OutputWord(){
//********************************************************
stack<char> s; //定義一個棧
int i;
for(i = 0;i < n;i++){
int k = i;
while(k != -1){
s.push(dict[k].last_char);
k = dict[k].index;
}
while(!s.empty()){
char c = s.top();
s.pop();
printf("%c",c);
}
printf("\n");
}
//========================================================
}
int main(){
FILE *fp;
if((fp=fopen("DictS.in", "r")) != NULL ){
fclose(fp); //存在的話,要先把之前打開的文件關掉
freopen("DictS.in", "r", stdin);
freopen("DictS.out", "w", stdout);
}
ini();
OutputWord();
return 0;
}