关于单链表,二叉树,图,查找和排序的软件编程
課程名稱:計算機軟件
使用軟件:devcpp
注意:這里列出了關于單鏈表,二叉樹,圖,查找和排序的編程,全部程序由博主一人編寫,會有瑕疵,謹慎使用。
1.單鏈表
要求:(1)建立單向鏈表,表長任意;
? ? ? ? ?? (2)可交互輸出單鏈表中的內容;
? ? ? ? ?? (3)編寫算法計算出自己所建單鏈表的長度并輸出;
? ? ? ? ?? (4)刪除自己所建單鏈表中的第K個結點,并將剩余結點輸出;
? ? ? ? ?? (5)將單鏈表倒排,輸出結果。
程序:
#include <stdio.h>?
#include <stdlib.h>
//定義鏈表中的節點?
struct node
{? unsigned char data;//鏈表中的數據?
?? struct node * next;//指向下一節點的指針?
};
//變量定義
struct node? *p,*p1,*p2,*head;
//函數聲明
void ListCreate();
void ListTraverse();
void ListLength();
int ListDelete();
int ListReverse();
//主函數?
int main()
{
?ListCreate();??????? //單向鏈表的建立
?ListTraverse();????? //單向鏈表的輸出
?ListLength();??????? //單向鏈表長度計算
?ListDelete();??????? //單向鏈表結點的刪除
?ListReverse();????? //單鏈表的倒排?
}
//單向鏈表的建立
void ListCreate()
{???
??? head=p=(struct node * )malloc(sizeof(struct node));
?printf("請輸入鏈表數據元素值(0為結束標志,中間不能用任何符號):\n");?
??? scanf("%c",&p->data);//頭結點的數據成員?
??? while(p->data!='0')//給出0結束條件,退出循環
??? {???
?? p1=p;?
????? p=(struct node * )malloc(sizeof(struct node));?
????? scanf("%c",&p->data);//中間結點數據成員
????? p1->next=p;//中間結點的指針成員值
??? }?
??? p->next=NULL;//尾結點的指針成員值?
}
//單向鏈表的輸出
void ListTraverse()
{?
??? p=head;
??? printf("\n鏈表數據成員是:");?
??? while(p->next!=NULL)?
??? {?
????? printf("%c? ",p->data);? //輸出成員數據
????? p=p->next;?
??? }???
}
//單向鏈表長度計算
void ListLength()
{
??? p2=head->next;
??? int? j=1;??????????? //j用來存放鏈表的長度
??? while((p2->data)-48)
??? {
????? p2=p2->next;
????? j++;
??? }
??? printf("\n鏈表長度是:? %d",j);
}
//單向鏈表結點的刪除
int ListDelete()
{
??? p2 = head;
??? int j = 1,M,K;
???
??? printf("\n要刪除第幾個節點: ");
?scanf("%d",&K);
??? if ( j > (K-1)) //刪除頭節點
?? {
????? struct node? *p3;
????? p3=p2;
????? p2=p3->next;
??? }
??? else?? //刪除其它節點
??? {
??? while ((p2->next)-48 && j < (K-1))
?{
??????? p2 = p2->next;
??????? ++j;
??? }
???? if (p2->next == NULL )
?{
??????? printf("Position Error\n");
??????? return 0;
??? }
??? struct node *temp = p2->next;? //執行刪除操作
??? p2->next = temp->next;
??? }???
??? p=head;
??? printf("刪除后的鏈表數據成員是:");?
??? while(p->next!=NULL)?
??? {?
????? printf("%c? ",p->data);? //輸出成員數據
????? p=p->next;?
??? }?
}
//單鏈表的倒排
int ListReverse()
{
??? struct node *h,*h1,*h2;
??? h=head;
??? h1=h;????????????????????
??? h=NULL;
??? while(h1->next!=NULL)????? //通過循環使h從最后一個元素依次向前
??? {?
??????? h2 = h1->next;?
??????? h1->next = h;?
??????? h = h1;?
??????? h1 = h2;
??? }??
??? printf("\n倒排后的鏈表數據成員是:");?
??? while(h!=NULL)? //輸出數據元素
??? {?
????? printf("%c? ",h->data);?
????? h=h->next;?
??? }??
}
?
難點:單鏈表的倒排,這里有兩種方法實現
1)逆序單鏈表的循環算法:
1 LINK_NODE *ReverseLink(LINK_NODE *head)2 {3 LINK_NODE *next; 4 LINK_NODE *prev = NULL; 5 6 while(head != NULL) 7 { 8 next = head->next; 9 head->next = prev; 10 prev = head; 11 head = next; 12 } 13 14 return prev; 15 }2)逆序單鏈表的遞歸算法:
1 LINK_NODE *ReverseLink2(LINK_NODE *head)2 {3 LINK_NODE *newHead; 4 5 if((head == NULL) || (head->next == NULL)) 6 return head; 7 8 newHead = ReverseLink2(head->next); /*遞歸部分*/ 9 head->next->next = head; /*回朔部分*/ 10 head->next = NULL; 11 12 return newHead; 13 }循環還是遞歸?這是個問題。當面對一個問題的時候,不能一概認為哪種算法好,哪種不好,而是要根據問題的類型和規模作出選擇。對于線性數據結構,比較適合用迭代循環方法,而對于樹狀數據結構,比如二叉樹,遞歸方法則非常簡潔優雅。原文鏈接:https://blog.csdn.net/lycnjupt/article/details/47103433
如果想了解關于逆序單鏈表的其它實現方法,可以查看鏈接:
http://blog.sina.com.cn/s/blog_68e4d2910100tc0i.html
?
2.二叉樹
要求:(1)動態交互建立二叉樹,結點個數任意;
? ? ? ? ?? (2)分別用DLR,LDR,LRD三種方式對二叉樹進行遍歷,并輸出結果;
? ? ? ? ?? (3)計算二叉樹中的結點個數并輸出;
? ? ? ? ?? (4)計算二叉樹的深度并輸出。
我自己的程序:
#include <stdio.h>
#include <stdlib.h>
//節點聲明,數據域、左指針、右指針
typedef struct BiTNode
{
?? int data;//二叉樹數據元素
?? struct BiTNode *Left,*Right;//二叉樹左右指針
}BiTNode,*BiTree;
//函數聲明
int CreateBiTree(BiTNode **T);
void DLR_BiTree(BiTNode *T);
void LDR_BiTree(BiTNode *T);
void LRD_BiTree(BiTNode *T);
int BiTreeCount(BiTNode *T);
int BiTreeDeep(BiTNode *T);
//主函數
int main()
{
?? BiTree T;
?? int depth,Count = 0;
??
?? printf("請輸入第一個節點的值(0表示沒有該節點): ");
?? CreateBiTree(&T);//二叉樹建立
?? printf("\n");
??
?? printf("先序遍歷二叉樹:");
?? DLR_BiTree(T);//二叉樹先序遍歷
?? printf("\n");
??
?? printf("中序遍歷二叉樹:");
?? LDR_BiTree(T);//二叉樹中序遍歷
?? printf("\n");
??
?? printf("后序遍歷二叉樹:");
?? LRD_BiTree(T);//二叉樹后序遍歷
?? printf("\n");
??
?? Count = BiTreeCount(T);//求二叉樹結點個數??
?? printf("二叉樹結點個數:%d\n",Count);?
??
?? depth = BiTreeDeep(T);//求二叉樹深度?
?? printf("二叉樹的深度為:%d\n",depth);
}
//先序創建二叉樹?
int CreateBiTree(BiTNode **T)?
{?
??? int ch;?
??? scanf("%d",&ch);//給二叉樹第一個節點賦值?
??? if (ch == 0)?
??? {?
??????? *T = NULL;? //輸入為0表示沒有該節點
??????? return 0;?
??? }?
??? else?
??? {?
??????? *T = (BiTNode *)malloc(sizeof(BiTNode));? //給二叉樹節點分配內存
??????? if (T == NULL)?
??????? {?
??????????? printf("failed\n");?
??????????? return 0;?
??????? }?
??????? else?
??????? {?
??????????? (*T)->data = ch;?
??????????? printf("輸入%d的左子節點:",ch);?
??????????? CreateBiTree(&((*T)->Left));? //遞歸給二叉樹左節點賦值
??????????? printf("輸入%d的右子節點:",ch);?
??????????? CreateBiTree((&(*T)->Right)); //遞歸給二叉樹右節點賦值
??????? }?
??? }?
?
??? return 1;?
}
//二叉樹先序遍歷
void DLR_BiTree(BiTNode *T)
{
?if( T == NULL) return;//遞歸調用的結束條件
?printf("%d",T->data);//訪問節點的數據域
?DLR_BiTree(T->Left);//先序遞歸遍歷左子樹
?DLR_BiTree(T->Right);//先序遞歸遍歷右子樹
}
//二叉樹中序遍歷
void LDR_BiTree(BiTNode *T)
{
?if(T==NULL) return;//遞歸調用的結束條件
?LDR_BiTree(T->Left);//中序遞歸遍歷左子樹
?printf("%d",T->data);//訪問節點的數據域
?LDR_BiTree(T->Right);//中序遞歸遍歷右子樹
}
//二叉樹后序遍歷
void LRD_BiTree(BiTNode *T)
{
?if(T==NULL) return;//遞歸調用的結束條件
?LRD_BiTree(T->Left);//后序遞歸遍歷左子樹
?LRD_BiTree(T->Right);//后序遞歸遍歷右子樹
?printf("%d",T->data);//訪問節點的數據域
}
//求二叉樹結點個數
int BiTreeCount(BiTNode *T)
{
??? if(T==NULL)
??????? return 0;//空二叉樹結點數為0
??? else???????????????????????????
??????? return BiTreeCount(T->Left)+BiTreeCount(T->Right)+1;//左右子樹結點總數加1
}
?
//求二叉樹深度
int BiTreeDeep(BiTNode *T)?
{?
??? int deep = 0;?
??? if (T != NULL)?
??? {?
??????? int leftdeep = BiTreeDeep(T->Left);//遞歸得到左子樹深度?
??????? int rightdeep = BiTreeDeep(T->Right);//遞歸得到右子樹深度
??????? deep = leftdeep >= rightdeep?leftdeep+1:rightdeep+1;//比較得到二叉樹深度?
??? }?
?
??? return deep;?
}?
?
3.圖
要求:(1)根據教材上算法,完成圖的深度和廣度優先遍歷,要求任意給定起始點,輸出結果。
? ? ? ? ? (2)根據教材上算法,完成圖的單元最短路徑的算法,要求任意給定源點,輸出結果。
程序:
#include <stdio.h> #include <stdlib.h>#define MAXVEX 100 //最大頂點數 #define INFINITY 65535 //用65535來代表無窮大 //定義訪問標記 int visited[MAXVEX]={0}; //定義圖結構體 typedef struct { char vexs[MAXVEX]; //頂點表 int arc[MAXVEX][MAXVEX]; //鄰接矩陣,可看作邊 int numVertexes, numEdges; //圖中當前的頂點數和邊數 }Graph; //輔助數組中的元素定義 typedef struct { int distance; int path[MAXVEX]; }ArrayNode;//函數聲明 void CreateGraph(Graph *g); void DFS(Graph g,int v); void BFS(Graph g,int v); void SHORT(Graph *g,int from,int to); void SHORT(Graph *g,int from,int to);//主函數 int main() {Graph g;int i,from,to;printf("t為1-4,分別表示無向圖、有向圖、帶權無向圖、帶權有向圖\n");CreateGraph(&g);//創建圖 printf("\n輸入遍歷起點: "); scanf("%d",&i); printf("\n深度優先搜索遍歷:");DFS(g,i);//深度優先遍歷函數 printf("NULL\n");printf("廣度優先搜索遍歷:"); BFS(g,i);//廣度優先遍歷函數 printf("NULL\n");printf("\nDijkstra算法單元最短路徑:");printf("\n請輸入起點和終點(中間用空格):");scanf("%d %d",&from,&to);SHORT(&g,from,to);//Dijkstra算法單元最短路徑函數 }//創建圖 void CreateGraph(Graph *g) { int i,j,k,w,t; printf("輸入頂點數,邊數和t(中間用空格):"); scanf("%d %d %d", &(g->numVertexes), &(g->numEdges),&t); printf("\n"); for(i=1;i<=g->numVertexes;i++)//通過循環輸入頂點信息 { getchar(); printf("輸入第%d頂點信息vexs[%d]=",i,i); scanf("%c",&(g->vexs[i])); } printf("\n"); for(i=1;i<=g->numVertexes;i++) for(j=1;j<=g->numVertexes;j++) if (t>2) g->arc[i][j] = INFINITY;//區別是否帶權值 else g->arc[i][j]=0; for(k=1;k<=g->numEdges;k++)//通過循環輸入邊的信息 { printf("輸入有聯系的兩個頂點(中間用空格):"); scanf("%d %d",&i,&j); if(i>g->numVertexes ||j>g->numVertexes) exit(0); if(t>2) { printf("輸入權值:"); scanf("%d",&w); g->arc[i][j]=w; if(t==3) g->arc[j][i]=w; } else { g->arc[i][j]=1; if (t==1) g->arc[j][i]=1; } } printf("\n"); printf("輸出鄰接矩陣:\n"); for(i=1;i<=g->numVertexes ;i++) { for(j=1;j<=g->numVertexes ;j++) { printf("%8d",g->arc[i][j]); //輸出鄰接矩陣 /*if(t>2&&g->arc[i][j]==65535) g->arc[i][j]=0; else if(t>2&&g->arc[i][j]!=65535) g->arc[i][j]=1; */ } printf("\n"); } } //深度優先遍歷 void DFS(Graph g,int v) {int j; printf("%d->",v); //輸出訪問頂點 visited[v]=1; //全局數組訪問標記置1表示已經訪問 for(j=1; j<=g.numVertexes; j++) if ((g.arc[v][j]!=0)&&(g.arc[v][j]!=65535)&&(!visited[j])) DFS (g,j);//遞歸訪問非0非無窮頂點 } //廣度優先遍歷 void BFS(Graph g,int v) {int q[g.numVertexes+1] ; int i,f,r,j ;for(i=0;i<g.numVertexes;i++)visited[i]=0; //重置訪問標記 f=r=0 ; printf("%d->",v);//輸出第一個頂點 visited[v]=1 ;//標記已訪問 r++; q[r]=v; while (f<r) { f++; v=q[f]; for (j=1; j<=g.numVertexes; j++) //廣度優先遍歷依次訪問與上一頂點有聯系的點 {if ((g.arc[v][j]!=0)&&(g.arc[v][j]!=65535)&&(!visited[j])) { printf("%d->",j);//輸出訪問頂點 visited[j]=1 ; r++; q[r]=j ; }} } } //單元最短路徑算法 void SHORT(Graph *g,int from,int to) {int i,j,index=-1; int n=1;//記錄已經求出的兩個點之間的最短距離的個數 ArrayNode shortestPath[MAXVEX]; int flag[MAXVEX]={0};//標記,為1表示到這個頂點的最短距離已求出 //1.求from到各個頂點的直接距離,即初始化shortestPath數組 for(i=1;i<=g->numVertexes;i++){ if(from==i){ shortestPath[i].distance=0; shortestPath[i].path[0]=i; flag[from]=1; } else if(g->arc[from][i]>0){ shortestPath[i].path[0]=from; shortestPath[i].path[1]=i; shortestPath[i].distance=g->arc[from][i]; }else shortestPath[i].distance=INFINITY; } //2.每次求一個最短路徑 while(n<=g->numVertexes){ //選擇shortestPath中距離最小的,求出from到這個頂點的最短路徑 index=-1; for(i=1;i<=g->numVertexes;i++){ if(i==from) continue; if(flag[i]==0 && index==-1 && shortestPath[i].distance!=INFINITY) index=i; if(flag[i]==0 && index!=-1 && shortestPath[i].distance<shortestPath[index].distance) index=i; } flag[index]=1; //修改到各個頂點的最短路徑 for(i=1;i<=g->numVertexes;i++){ if(i==from) continue; if(g->arc[index][i]>0 && g->arc[index][i]+shortestPath[index].distance<shortestPath[i].distance){ shortestPath[i].distance=g->arc[index][i]+shortestPath[index].distance; //修改路徑 j=0; while(1){ shortestPath[i].path[j]=shortestPath[index].path[j]; if(shortestPath[index].path[j]==index) break; j++; } shortestPath[i].path[j+1]=i; } } n++; } //輸出from到to的最短路徑及長度 if(shortestPath[to].distance==INFINITY){ printf("%d到%d沒有路徑\n",from,to); return; } printf("%d到%d的最短路徑長度是:%d\n",from,to,shortestPath[to].distance); printf("經過的頂點: "); i=0; while(1){ printf("%-3d",shortestPath[to].path[i]); if(shortestPath[to].path[i]==to) break; i++; } printf("\n"); }4.查找和排序
要求:(1)任意給定無序序列,用對半檢索法,交互檢索任意給定的關鍵字KEY;
? ? ? ? ?? (2)任意給定無序序列,用快速排序法對序列進行排序,并統計交換次數;
? ? ? ? ?? (3)任意給定無序序列,用冒泡排序法對序列進行排序,并統計交換次數和排序趟數。
程序:
#include "stdio.h" #define N 6//序列長度(可修改)//函數聲明 int halfSort(int *b,int n); void quickSort(int *b,int l,int r); void bubbleSort(int *bb,int r);//全局變量定義 int o,p,k; int KEY; //檢索的關鍵字 //主函數 int main() {int i,j,q;int a[100],aa[100],aaa[100];//以數組方式定義序列 printf("Hello World!\n");printf("\n1.請輸入任意序列(用回車隔開)\n");for(i=1;i<=N;i++)scanf("%d",&a[i]);//輸入無序序列 quickSort(a,1,N);//先排序再進行對半檢索printf("排序后序列為:");for(j=1;j<=N;j++)printf("%d ",a[j]);//輸出有序序列 printf("\n請輸入需要檢索的關鍵字KEY:"); scanf("%d ",&KEY);q=halfSort(a,N);//對半檢索函數調用 printf("對半檢索-關鍵字位置為:%d\n",q);printf("\n2.請輸入任意序列(用回車隔開)\n");for(i=0;i<N;i++)scanf("%d",&aa[i]);//輸入無序序列 quickSort(aa,0,N-1);//快速排序函數調用 printf("快速排序后序列為:");for(j=0;j<N;j++)printf("%d ",aa[j]);//輸出有序序列 printf("\n交換次數為:%d\n",k);printf("\n3.請輸入任意序列(用回車隔開)\n");for(i=0;i<N;i++)scanf("%d",&aaa[i]);//輸入無序序列 bubbleSort(aaa,N);printf("冒泡排序后序列為:");//冒泡排序函數調用 for(j=0;j<N;j++)printf("%d ",aaa[j]);//輸出有序序列 printf("\n交換次數為:%d\n",o);printf("排序趟數為:%d\n",p);return 0; }//對半檢索函數 int halfSort(int *b,int n) {int high,mid,low;int rs=0;low=1;high=n;//初始狀態 while(low<=high)//判斷查找是否結束 {mid=(low+high)/2;if(KEY<b[mid]) high=mid-1;//關鍵字在前半區 elseif(KEY>b[mid]) low=mid+1;//關鍵字在后半區 else {rs=mid;break;}}return rs; }//快速排序函數 void quickSort(int *bb,int l,int r) {int m,n;int temp;if(l>=r) return;//只有一個記錄或無記錄,無須排序 m=l;n=r;temp=bb[m];while(m!=n)//尋找temp的最終位置 {while((bb[n]>=temp)&&(n>m))n--;//從右向左掃描,查找第一個小于temp的記錄 if(m<n){bb[m++]=bb[n];k++;}while((bb[m]<=temp)&&(n>m))m++;//從左向右掃描,查找第一個大于temp的記錄 if(m<n){bb[n--]=bb[m];k++;}}bb[m]=temp;//找到temp的最終位置 quickSort(bb,l,m-1);//遞歸處理左區間 quickSort(bb,m+1,r);//遞歸處理右區間 }//冒泡排序函數 void bubbleSort(int *bbb,int r) {int m,n,noswap;int temp;for(m=0;m<(r-1);m++)//外循環,做N-1次起泡 {noswap=1;for(n=0;n<(r-m-1);n++)//內循環,置交換標志 if(bbb[n+1]<bbb[n])//比較 {temp=bbb[n];bbb[n]=bbb[n+1];bbb[n+1]=temp;//交換 o++;noswap=0;}if(noswap) break;//本趟起泡未發生記錄交換,算法結束 p++;} }
轉載于:https://www.cnblogs.com/BoBoRing/p/8886094.html
總結
以上是生活随笔為你收集整理的关于单链表,二叉树,图,查找和排序的软件编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到自己腿流血了是什么预兆
- 下一篇: 梦到几条蛇咬我