PTA資料結構與演算法題目集(中文) 函式題(2)
4-6 帶頭結點的鏈式表操作集
code:
List MakeEmpty() { List L; L = (List)malloc(sizeof(struct LNode)); L->Data = NULL; L->Next = NULL; return L; } Position Find( List L, ElementType X ) { List p = L; while(p && p->Data!=X) { p = p->Next; } if(p && X==p->Data) { return p; } else { return ERROR; } } bool Insert( List L, ElementType X, Position P ) { List r = L; List pre = L; while(r && P!=r) { pre = r; r = r->Next; } if(r==P) { List p = (List)malloc(sizeof(struct LNode)); p->Data = X; p->Next = r; pre->Next = p; return true; } printf("Wrong Position for Insertion\n"); return false; } bool Delete( List L, Position P ) { List r = L; List pre = L; while(r && r!=P) { pre = r; r = r->Next; } if(r==P) { pre->Next = P->Next; free(P); List k = pre->Next; return true; } printf("Wrong Position for Deletion\n"); return false; }
P.S:這道題需要寫四個函式,分別是連結串列的置空,查詢某個元素,還有元素的插入和刪除,都是一些連結串列的基本操作,題中的連結串列是有頭節點的,而開始的題中的連結串列是沒有使用頭節點的,這個與前面的有一些區別,其實擁有頭節點的連結串列更容易操作,在插入時不用考慮是否是第一個結點了,更加好寫些,同樣要注意Find函式,它需要返回的是這個元素的Position,而它是一個指標變數,而不是代表其位置的整型變數。
4-7 在一個數組中實現兩個堆疊
P.S:很頭疼,這一題沒有通過,報的錯誤也是十分無奈,超時,所以也不知道怎樣去解決這個問題,如何去優化程式碼,這道題其實是一個數組嘛,兩個棧的棧底在兩頭,設計應該就是這樣,但是給我報超時錯誤,暫時先放下吧,以後通過再補上來。
更新:補上成功的code,今天突然再次提交,居然就通過了,看來我的想法是沒有問題的^_^
code:
Stack CreateStack( int MaxSize )
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S->MaxSize = MaxSize;
S->Data = (ElementType *)malloc(sizeof(ElementType)*MaxSize);
S->Top2 = MaxSize;
S->Top1 = -1;
return S ;
}
bool Push(Stack S, ElementType X, int Tag){
if(S->Top1+1 == S->Top2){
printf("Stack Full\n");
return false;
}else{
if(Tag == 1){
S->Top1++;
S->Data[S->Top1] = X;
}else{
S->Top2--;
S->Data[S->Top2] = X;
}
}
return true;
}
ElementType Pop(Stack S, int Tag){
int X;
if(Tag == 1){
if(S->Top1 == -1){
printf("Stack 1 Empty\n");
return ERROR;
}else{
X = S->Data[S->Top1];
S->Top1--;
return X;
}
}else if(Tag == 2){
if(S->Top2 == S->MaxSize){
printf("Stack 2 Empty\n");
return ERROR;
}else{
X = S->Data[S->Top2];
S->Top2++;
return X;
}
}
}
4-8 求二叉樹高度
code:
int GetHeight( BinTree BT )
{
if (BT == NULL)
return 0;
else {
int left = GetHeight(BT->Left);
int right = GetHeight(BT->Right);
if(left>=right)
return 1 + left;
else
return 1 + right;
}
}
P.S:求一顆二叉樹的高度,我直接使用了遞迴實現,所以也十分的清晰易懂。
4-9 二叉樹遍歷
這道題吧,也木有通過,其實是不願寫吧,前序,中序,後續遍歷都很簡單,但是層序便利時,我們知道需要藉助佇列來實現,而在函式題中又不能用那種標頭檔案,因此我想了想,但後來腦子就不舒服,先放下,後面補上。
更新:今天想了想,其實沒有必要用佇列的,可以簡單點嘛,開始怎麼就那麼蠢呢,佇列也是由陣列或連結串列構成的,而這道題又不需要考慮佇列滿或者空的情況,自己用一個數組代替不就是了,其實很簡單的啦,我才用了一個容量為100的陣列來模擬佇列,最後就這樣成功啦,前中後三種遍歷就沒有什麼好說的咯,遞迴,簡單易懂,用棧的話也不難,但是能簡單就簡單嘛
code:
void InorderTraversal( BinTree BT ){
if(BT){
InorderTraversal(BT->Left);
printf(" %c", BT->Data);
InorderTraversal(BT->Right);
}
}
void PreorderTraversal( BinTree BT ){
if(BT){
printf(" %c",BT->Data);
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
}
}
void PostorderTraversal( BinTree BT )
{
if(BT != NULL){
PostorderTraversal(BT->Left);
PostorderTraversal(BT->Right);
printf(" %c", BT->Data);
}
}
void LevelorderTraversal( BinTree BT ) {
BinTree str[100];
int rear = -1, front = -1;
BinTree T;
if(!BT)
return;
rear = rear+1;
str[rear] = BT;
while(rear != front){
front = front+1;
T = str[front];
printf(" %c", T->Data);
if(T->Left) {
rear = rear+1;
str[rear] = T->Left;
}
if(T->Right){
rear++ ;
str[rear] = T->Right;
}
}
}
4-10 二分查詢
code:
Position BinarySearch( List Tbl, ElementType K )
{
int left, right, middle;
left = 1, right = Tbl->Last;
while (left <= right)
{
middle = (left + right) / 2;
if (Tbl->Data[middle] > K)
{
right = middle - 1;
}
else if (Tbl->Data[middle] < K)
{
left = middle + 1;
}
else if(Tbl->Data[middle] == K)
{
return middle;
}
}
return NotFound;
}
P.S:二分查詢演算法,也叫折半查詢,也就是將陣列每次只查詢一半,因此可以省去很多的比較次數,也就提高了效率,減少了查詢時間,是一個很好,很基礎的演算法
*
4-11 先序輸出葉結點
code:
void PreorderPrintLeaves( BinTree BT ){
if(BT != NULL){
PreorderPrintLeaves(BT->Left);
if(BT->Data >='A' && BT->Data <='z' && BT->Left == NULL && BT->Right == NULL){
printf(" %c",BT->Data);
}
PreorderPrintLeaves(BT->Right);
}
}
P.S:先序輸出葉子結點,說白了就是先序遍歷唄,不過在先序遍歷的基礎上進行一下判斷,當左右子節點都為空時才輸出來。
4-12 二叉搜尋樹的操作集
P.S:這道題部分正確,可能是沒有考慮全面,前三個測試點不能通過,後兩個可以,所以等通過之後再放上程式碼。
更新:調了很多次,這道雖然是教材上的,但是刪除操作是真的很複雜,需要很細心頭腦很清晰的去寫,下面的是code,參考了教材上的原始碼,最後居然讓我發現了一個小錯誤,教材上查詢最大最小元素函式的判斷語句中多了個“!”,很容易就發現啦,但是不一定會注意到,慢慢寫啦!!
code:
BinTree Insert( BinTree BST, ElementType X )
{
if(!BST) { /* 若原樹為空,生成並返回一個結點的二叉搜尋樹 */
BST = (BinTree)malloc(sizeof(struct TNode));
BST ->Data = X;
BST ->Left = BST ->Right = NULL;
}else { /* 開始尋找要插入元素的位置 */
if(X < BST ->Data ) {
BST ->Left = Insert(BST ->Left, X);
}else if(X > BST ->Data ) {
BST ->Right = Insert(BST ->Right, X);
}
/* X已經存在,不用操作 */
}
return BST;
}
BinTree Delete( BinTree BST, ElementType X )
{
Position Tmp;
if(!BST) {
printf("Not Found\n");
}else {
if( X < BST->Data) {
BST ->Left = Delete(BST->Left, X); /* 左子樹遞迴刪除 */
}else if(X > BST->Data ) {
BST ->Right = Delete(BST->Right , X); /* 右子樹遞迴刪除*/
}else { /* 找到需要刪除的結點 */
if(BST->Left && BST->Right) {
/* 被刪除的結點有左右子結點 */
Tmp = FindMin( BST ->Right); /* 在右子樹中找到最小結點填充刪除結點 */
BST ->Data = Tmp ->Data;
BST ->Right = Delete(BST ->Right, BST ->Data); /* 在刪除結點的右結點中刪除最小元素 */
}else { /* 被刪除結點有一個或沒有子結點*/
Tmp = BST;
if(!BST ->Left) { /*有右孩子或無子結點*/
BST = BST->Right;
}else if(!BST->Right) { /* 有左孩子或無子節點*/
BST = BST->Left;
}
free(Tmp);
}
}
}
return BST;
}
Position Find( BinTree BST, ElementType X )
{
if(!BST) {
return NULL; // 查詢失敗
}
if(X > BST->Data) {
return Find(BST->Right, X); //在右子樹中繼續查詢
}else if(X < BST->Data) {
return Find(BST->Left, X); //在左子樹中繼續查詢
}else {
return BST; //查詢成功
}
}
Position FindMin( BinTree BST )
{
if(BST) {
while(BST->Left) {
BST = BST->Left; //沿著左分支一直查詢,直到葉子結點
}
}
return BST;
}
Position FindMax( BinTree BST )
{
if(BST) {
while(BST->Right) {
BST = BST->Right; //沿著右分支一直查詢,直到葉子結點
}
}
return BST;
}
函式題就這12道,其中已經完全通過了9道,還有3道暫時沒有通過,要不超時,要不部分正確,暫時想也想不出來,想的也比較難過,所以等什麼時候有空無聊時再想想,然後通過了再補上吧,如果能給予想法的話請聯絡我呀,一起交流,一起分享,一起進步^_^
今天將原先沒放上的都解決啦,12道函式題完成,雖然都是很基礎的資料結構,但是真要全部靠自己寫出來很困難困難,多多練習咯,後面就慢慢刷程式設計題咯,刷題的快感~~~