1. c語言怎麼用自定義函數排序
#include <stdio.h>
#include <string.h>#define NUM 3
struct student
{
char name[20]; /*姓名*/
long num; /*12位學號*/
double sum; /*總分*/
};
void Create_Students(struct student stu[NUM])
{
struct student *p;
printf("請輸入學生姓名 學號(12位) 總分:\n");
for( p = stu; p <stu+NUM; p++)
{
scanf("%s %d %lf",p->name,&p->num,&p->sum); }
}
void Order_Students(struct student stu[NUM])//起泡法
{
int i,j;
struct student temp;
for(i=NUM-1;i>=0;i--)
for(j=0;j<i;j++)
if(stu[j].sum<stu[j+1].sum)
{
temp = stu[j];
stu[j] = stu[j+1];
stu[j+1]=temp;
}
}
void main()
{
int i=1;
struct student *p;
struct student stu[NUM];
Create_Students(stu);
Order_Students(stu);
printf("%-20s %-13s %-6s %4s\n","姓名","學號(12位)","總成績","名次");
for(p=stu;p<stu+NUM;p++,i++)
{
printf("%-20s %-13.0d %-8.2f %2d\n",p->name,p->num,p->sum,i);
}
}//你參考參考,嘿
2. c語言 排序函數
首先這是一種快速排序的演算法,你也應該知道,快速排序就是選擇序列中的一個元素作為基準,通過循環找到這個基準最終的位置,並把所有小於這個基準的元素移到這個位置的左邊,大於基本的元素移到右邊,這樣再對這個基準的左右兩邊分別遞歸調用自己,最終就能得到排序的結果。
再來解釋一下這個例子,它選擇的基準就是v[(left+right)/2],然後將這個基準雨v[left]交換,現在假設你想從頭排序到最後,則你會將left傳個0,也就是他將這個基準和V[0]交換了,這個時候開始循環,因為第一個元素是基準,所以從第二個元素開始循環(也就是left+1),然後到if判斷部分,如果v[i]<v[left],也就是說這個時候已經至少有一個元素比基準小了,所以基準至少在v[1]或者之後了,所以他把你找到的這個比基準小的v[i]和v[++last]交換,這時候v[i]的位置已經是在基準的正確位置或者之前了,不會在基準之後的,所以這就實現了把比基準小的元素移到基準的正確位置之前,你說的【第一遍執行過程中,第8行last=left=0,那麼到了11行時相當於交換v[1]和v[0+1]】這沒有錯,確實是在自己交換自己,但是這樣並不違背前面的思路不是么?當if條件不滿足的時候,last是不會增加的,但是i會一直加1,所以last和i就會不同,這只是在將比基準小的元素移到基準之前,每有一個比基準小的,last就加1,這樣當你循環一遍之後的last值就是基準應該在的位置,而且這個時候,所有比基本小的元素也都在last之前了,這時候last位置的元素也是比基準小的,這沒關系,因為之後還有一句swap[v,last,left],到目前位置,基準的位置找到了,基準左邊的元素都比基準小,右邊都比基準大,再對基準的左右兩邊遞歸調用自己,就完成了序列的排序。
3. 怎樣用C語言對一串整行數從大到小排序
方法太多了,當然各種時間排序的時間復雜度和空間復雜度不同、穩定性也不同。最簡單的我覺得就是冒泡排序了,也最形像。/*
================================================
功能:選擇排序
輸入:數組名稱(也就是數組首地址)、數組中元素個數
================================================
*/
/*
====================================================
演算法思想簡單描述: 在要排序的一組數中,選出最小的一個數與第一個位置的數交換;
然後在剩下的數當中再找最小的與第二個位置的數交換,如此循環
到倒數第二個數和最後一個數比較為止。 選擇排序是不穩定的。演算法復雜度O(n2)--[n的平方]
=====================================================
*/
void select_sort(int *x, int n)
{
int i, j, min, t; for (i=0; i<n-1; i++) /*要選擇的次數:0~n-2共n-1次*/
{
min = i; /*假設當前下標為i的數最小,比較後再調整*/
for (j=i+1; j<n; j++)/*循環找出最小的數的下標是哪個*/
{
if (*(x+j) < *(x+min))
{
min = j; /*如果後面的數比前面的小,則記下它的下標*/
}
}
if (min != i) /*如果min在循環中改變了,就需要交換數據*/
{
t = *(x+i);
*(x+i) = *(x+min);
*(x+min) = t;
}
}
}
/*
================================================
功能:直接插入排序
輸入:數組名稱(也就是數組首地址)、數組中元素個數
================================================
*/
/*
====================================================
演算法思想簡單描述: 在要排序的一組數中,假設前面(n-1) [n>=2] 個數已經是排
好順序的,現在要把第n個數插到前面的有序數中,使得這n個數
也是排好順序的。如此反復循環,直到全部排好順序。
直接插入排序是穩定的。演算法時間復雜度O(n2)--[n的平方]
=====================================================
*/
void insert_sort(int *x, int n)
{
int i, j, t; for (i=1; i<n; i++) /*要選擇的次數:1~n-1共n-1次*/
{
/*
暫存下標為i的數。注意:下標從1開始,原因就是開始時
第一個數即下標為0的數,前面沒有任何數,單單一個,認為
它是排好順序的。
*/
t=*(x+i);
for (j=i-1; j>=0 && t<*(x+j); j--) /*注意:j=i-1,j--,這里就是下標為i的數,在它前面有序列中找插入位置。*/
{
*(x+j+1) = *(x+j); /*如果滿足條件就往後挪。最壞的情況就是t比下標為0的數都小,它要放在最前面,j==-1,退出循環*/
} *(x+j+1) = t; /*找到下標為i的數的放置位置*/
}
}
/*
================================================
功能:冒泡排序
輸入:數組名稱(也就是數組首地址)、數組中元素個數
================================================
*/
/*
====================================================
演算法思想簡單描述: 在要排序的一組數中,對當前還未排好序的范圍內的全部數,自上
而下對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較
小的往上冒。即:每當兩相鄰的數比較後發現它們的排序與排序要
求相反時,就將它們互換。
下面是一種改進的冒泡演算法,它記錄了每一遍掃描後最後下沉數的
位置k,這樣可以減少外層循環掃描的次數。 冒泡排序是穩定的。演算法時間復雜度O(n2)--[n的平方]
=====================================================
*/void bubble_sort(int *x, int n)
{
int j, k, h, t;
for (h=n-1; h>0; h=k) /*循環到沒有比較范圍*/
{
for (j=0, k=0; j<h; j++) /*每次預置k=0,循環掃描後更新k*/
{
if (*(x+j) > *(x+j+1)) /*大的放在後面,小的放到前面*/
{
t = *(x+j);
*(x+j) = *(x+j+1);
*(x+j+1) = t; /*完成交換*/
k = j; /*保存最後下沉的位置。這樣k後面的都是排序排好了的。*/
}
}
}
}
/*
================================================
功能:希爾排序
輸入:數組名稱(也就是數組首地址)、數組中元素個數
================================================
*/
/*
====================================================
演算法思想簡單描述:
在直接插入排序演算法中,每次插入一個數,使有序序列只增加1個節點,
並且對插入下一個數沒有提供任何幫助。如果比較相隔較遠距離(稱為
增量)的數,使得數移動時能跨過多個元素,則進行一次比較就可能消除
多個元素交換。D.L.shell於1959年在以他名字命名的排序演算法中實現
了這一思想。演算法先將要排序的一組數按某個增量d分成若干組,每組中
記錄的下標相差d.對每組中全部元素進行排序,然後再用一個較小的增量
對它進行,在每組中再進行排序。當增量減到1時,整個要排序的數被分成
一組,排序完成。
下面的函數是一個希爾排序演算法的一個實現,初次取序列的一半為增量,
以後每次減半,直到增量為1。 希爾排序是不穩定的。
=====================================================
*/
void shell_sort(int *x, int n)
{
int h, j, k, t; for (h=n/2; h>0; h=h/2) /*控制增量*/
{
for (j=h; j<n; j++) /*這個實際上就是上面的直接插入排序*/
{
t = *(x+j);
for (k=j-h; (k>=0 && t<*(x+k)); k-=h)
{
*(x+k+h) = *(x+k);
}
*(x+k+h) = t;
}
}
}/*
================================================
功能:快速排序
輸入:數組名稱(也就是數組首地址)、數組中起止元素的下標
================================================
*/
/*
====================================================
演算法思想簡單描述: 快速排序是對冒泡排序的一種本質改進。它的基本思想是通過一趟
掃描後,使得排序序列的長度能大幅度地減少。在冒泡排序中,一次
掃描只能確保最大數值的數移到正確位置,而待排序序列的長度可能只
減少1。快速排序通過一趟掃描,就能確保某個數(以它為基準點吧)
的左邊各數都比它小,右邊各數都比它大。然後又用同樣的方法處理
它左右兩邊的數,直到基準點的左右只有一個元素為止。它是由
C.A.R.Hoare於1962年提出的。
顯然快速排序可以用遞歸實現,當然也可以用棧化解遞歸實現。下面的
函數是用遞歸實現的,有興趣的朋友可以改成非遞歸的。 快速排序是不穩定的。最理想情況演算法時間復雜度O(nlog2n),最壞O(n2)
=====================================================
*/
void quick_sort(int *x, int low, int high)
{
int i, j, t; if (low < high) /*要排序的元素起止下標,保證小的放在左邊,大的放在右邊。這里以下標為low的元素為基準點*/
{
i = low;
j = high;
t = *(x+low); /*暫存基準點的數*/ while (i<j) /*循環掃描*/
{
while (i<j && *(x+j)>t) /*在右邊的只要比基準點大仍放在右邊*/
{
j--; /*前移一個位置*/
} if (i<j)
{
*(x+i) = *(x+j); /*上面的循環退出:即出現比基準點小的數,替換基準點的數*/
i++; /*後移一個位置,並以此為基準點*/
} while (i<j && *(x+i)<=t) /*在左邊的只要小於等於基準點仍放在左邊*/
{
i++; /*後移一個位置*/
} if (i<j)
{
*(x+j) = *(x+i); /*上面的循環退出:即出現比基準點大的數,放到右邊*/
j--; /*前移一個位置*/
}
} *(x+i) = t; /*一遍掃描完後,放到適當位置*/
quick_sort(x,low,i-1); /*對基準點左邊的數再執行快速排序*/
quick_sort(x,i+1,high); /*對基準點右邊的數再執行快速排序*/
}
}
/*
================================================
功能:堆排序
輸入:數組名稱(也就是數組首地址)、數組中元素個數
================================================
*/
/*
====================================================
演算法思想簡單描述: 堆排序是一種樹形選擇排序,是對直接選擇排序的有效改進。
堆的定義如下:具有n個元素的序列(h1,h2,...,hn),當且僅當
滿足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)
時稱之為堆。在這里只討論滿足前者條件的堆。 由堆的定義可以看出,堆頂元素(即第一個元素)必為最大項。完全二叉樹可以
很直觀地表示堆的結構。堆頂為根,其它為左子樹、右子樹。
初始時把要排序的數的序列看作是一棵順序存儲的二叉樹,調整它們的存儲順序,
使之成為一個堆,這時堆的根節點的數最大。然後將根節點與堆的最後一個節點
交換。然後對前面(n-1)個數重新調整使之成為堆。依此類推,直到只有兩個節點
的堆,並對它們作交換,最後得到有n個節點的有序序列。 從演算法描述來看,堆排序需要兩個過程,一是建立堆,二是堆頂與堆的最後一個元素
交換位置。所以堆排序有兩個函數組成。一是建堆的滲透函數,二是反復調用滲透函數
實現排序的函數。 堆排序是不穩定的。演算法時間復雜度O(nlog2n)。*/
/*
功能:滲透建堆
輸入:數組名稱(也就是數組首地址)、參與建堆元素的個數、從第幾個元素開始
*/
void sift(int *x, int n, int s)
{
int t, k, j; t = *(x+s); /*暫存開始元素*/
k = s; /*開始元素下標*/
j = 2*k + 1; /*右子樹元素下標*/ while (j<n)
{
if (j<n-1 && *(x+j) < *(x+j+1))/*判斷是否滿足堆的條件:滿足就繼續下一輪比較,否則調整。*/
{
j++;
} if (t<*(x+j)) /*調整*/
{
*(x+k) = *(x+j);
k = j; /*調整後,開始元素也隨之調整*/
j = 2*k + 1;
}
else /*沒有需要調整了,已經是個堆了,退出循環。*/
{
break;
}
}
*(x+k) = t; /*開始元素放到它正確位置*/
}
/*
功能:堆排序
輸入:數組名稱(也就是數組首地址)、數組中元素個數
*/
void heap_sort(int *x, int n)
{
int i, k, t;
int *p; for (i=n/2-1; i>=0; i--)
{
sift(x,n,i); /*初始建堆*/
}
for (k=n-1; k>=1; k--)
{
t = *(x+0); /*堆頂放到最後*/
*(x+0) = *(x+k);
*(x+k) = t;
sift(x,k,0); /*剩下的數再建堆*/
}
}
void main()
{
#define MAX 4
int *p, i, a[MAX];
/*錄入測試數據*/
p = a;
printf("Input %d number for sorting :\n",MAX);
for (i=0; i<MAX; i++)
{
scanf("%d",p++);
}
printf("\n"); /*測試選擇排序*/
p = a;
select_sort(p,MAX);
/**/
/*測試直接插入排序*/ /*
p = a;
insert_sort(p,MAX);
*/
/*測試冒泡排序*/ /*
p = a;
insert_sort(p,MAX);
*/ /*測試快速排序*/ /*
p = a;
quick_sort(p,0,MAX-1);
*/ /*測試堆排序*/ /*
p = a;
heap_sort(p,MAX);
*/ for (p=a, i=0; i<MAX; i++)
{
printf("%d ",*p++);
}
printf("\n");
system("pause");
}
4. C語言的全排列問題!急!
這其實是一個遞歸
遞歸函數
意思是這樣的
比如有n個數
1
2.。。。n
把1
從第一個開始
往後
與每個數開始交換
然後
第一個數就算定了
後面的
第2個到第n個當成一個整體
再進行這個函數遞歸
也就是說
第二個到第n個進行全排列
這樣下去
當全排列到最後一組數
即第n個數一個的時候
遞歸退出條件就出來了
就可以輸出全排列的值了
當然
最後別忘記把交換的數還原
再進行下一次交換
遞歸哦
所以最後一局的交換也是很重要的
聽完我的解釋
再好好琢磨一下
相信你一定會明白的
要是還是不懂可以繼續追問我
5. c語言中排序方法
1、冒泡排序(最常用)
冒泡排序是最簡單的排序方法:原理是:從左到右,相鄰元素進行比較。每次比較一輪,就會找到序列中最大的一個或最小的一個。這個數就會從序列的最右邊冒出來。(注意每一輪都是從a[0]開始比較的)
以從小到大排序為例,第一輪比較後,所有數中最大的那個數就會浮到最右邊;第二輪比較後,所有數中第二大的那個數就會浮到倒數第二個位置……就這樣一輪一輪地比較,最後實現從小到大排序。
2、雞尾酒排序
雞尾酒排序又稱雙向冒泡排序、雞尾酒攪拌排序、攪拌排序、漣漪排序、來回排序或快樂小時排序, 是冒泡排序的一種變形。該演算法與冒泡排序的不同處在於排序時是以雙向在序列中進行排序。
原理:數組中的數字本是無規律的排放,先找到最小的數字,把他放到第一位,然後找到最大的數字放到最後一位。然後再找到第二小的數字放到第二位,再找到第二大的數字放到倒數第二位。以此類推,直到完成排序。
3、選擇排序
思路是設有10個元素a[1]-a[10],將a[1]與a[2]-a[10]比較,若a[1]比a[2]-a[10]都小,則不進行交換。若a[2]-a[10]中有一個以上比a[1]小,則將其中最大的一個與a[1]交換,此時a[1]就存放了10個數中最小的一個。同理,第二輪拿a[2]與a[3]-a[10]比較,a[2]存放a[2]-a[10]中最小的數,以此類推。
4、插入排序
插入排序是在一個已經有序的小序列的基礎上,一次插入一個元素*
一般來說,插入排序都採用in-place在數組上實現。
具體演算法描述如下:
⒈ 從第一個元素開始,該元素可以認為已經被排序
⒉ 取出下一個元素,在已經排序的元素序列中從後向前掃描
⒊ 如果該元素(已排序)大於新元素,將該元素移到下一位置
⒋ 重復步驟3,直到找到已排序的元素小於或者等於新元素的位置
⒌ 將新元素插入到下一位置中
⒍ 重復步驟2~5