二叉樹
A
/ /
B C
/ / /
D E F
先序遍歷(前序遍歷,先根便利)
如果非空,先訪問根節點,再先序遍歷左子樹,最後先序遍歷右子樹,即NLR。
A->B->D->C->E->F
中序遍歷(中根便利)
如果非空,先中序遍歷左子樹,再訪問根節點,最後中序遍歷右子樹,即LNR。
D->B->A->E->C->F
後序遍歷(後根便利)
如果非空,先後序遍歷左子樹,再後序遍歷右子樹,最後訪問根節點,即LRN。
D->B->E->F->C->A
C代碼:
//二叉樹節點結構 typedef struct tag_stBiTreeNode { tag_stBiTreeNode * pstLchild; tag_stBiTreeNode * pstRchild; int iData; }BITREENODE, * PBITREENODE; //先序遍歷 void PreorderTraversal(const PBITREENODE pstBiRoot) { if(NULL != pstBiRoot) // 如果二叉树非空 { printf("0x%X/n", pstBiRoot->iData); // 先访问根结点 PreorderTraversal(pstBiRoot->pstLchild); PreorderTraversal(pstBiRoot->pstRchild); } return; } //PreorderTraversal //中序遍歷 void InorderTraversal(const PBITREENODE pstBiRoot) { if(NULL != pstBiRoot) // 如果二叉树非空 { InorderTraversal(pstBiRoot->pstLchild); printf("0x%X/n", pstBiRoot->iData); //访问结点 InorderTraversal(pstBiRoot->pstRchild); } return; } //InorderTraversal //後序遍歷 void PostorderTraversal(const PBITREENODE pstBiRoot) { if(NULL != pstBiRoot) // 如果二叉树非空 { InorderTraversal(pstBiRoot->pstLchild); InorderTraversal(pstBiRoot->pstRchild); printf("0x%X/n", pstBiRoot->iData); //访问结点 } return; } //PostorderTraversal /*功能:構建一顆二叉樹。遞歸版本。 先序構建。即先根,再左子樹,最後右子樹。 輸入空格即停止本次構建,但由於是遞歸,將返回上一層。 */ void CreateBiTree(PBITREENODE * ppstBiRoot) { char cInput = 0; printf("Please input:"); //scanf("%c", &cInput); cInput = getch(); printf("/n"); //cInput = getchar(); if(' ' == cInput) { *ppstBiRoot = NULL;//读入空格,将相应指针置空 } else { //读入非空格 *ppstBiRoot = (PBITREENODE)malloc(sizeof(BITREENODE));//生成结点 if(NULL == *ppstBiRoot) { //內存分配失敗,回滾操作省略 return; } //這三行的順序表明了是先序、中序還是後序插入數據 (*ppstBiRoot)->iData = cInput; CreateBiTree(&(*ppstBiRoot)->pstLchild);//构造左子树 CreateBiTree(&(*ppstBiRoot)->pstRchild);//构造右子树 } return; } //先序刪除 void PreorderDestory(PBITREENODE pstBiRoot) { PBITREENODE pstTempLchild = NULL; PBITREENODE pstTempRchild = NULL; if(NULL != pstBiRoot) // 如果二叉树非空 { //保存左右孩子節點 pstTempLchild = pstBiRoot->pstLchild; pstTempRchild = pstBiRoot->pstRchild; free(pstBiRoot); //釋放结点 pstBiRoot = NULL; PreorderDestory(pstTempLchild); PreorderDestory(pstTempRchild); } return; } //PostorderDestory //中序刪除 void InorderDestory(PBITREENODE pstBiRoot) { PBITREENODE pstTempRchild = NULL; if(NULL != pstBiRoot) // 如果二叉树非空 { //釋放左孩子 InorderDestory(pstBiRoot->pstLchild); //先保存右孩子節點 pstTempRchild = pstBiRoot->pstRchild; //釋放根節點 free(pstBiRoot); //釋放结点 pstBiRoot = NULL; InorderDestory(pstTempRchild); } return; } //PostorderDestory //後序刪除 void PostorderDestory(PBITREENODE pstBiRoot) { if(NULL != pstBiRoot) // 如果二叉树非空 { PostorderDestory(pstBiRoot->pstLchild); PostorderDestory(pstBiRoot->pstRchild); free(pstBiRoot); //釋放结点 pstBiRoot = NULL; } return; } //PostorderDestory // int _tmain(int argc, _TCHAR* argv[]) { PBITREENODE pstBiRoot = NULL; CreateBiTree(&pstBiRoot); PreorderTraversal(pstBiRoot); PostorderDestory(PstBiRoot); return 0; }
哈希表
// test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #define MAX 50 #define STATUSCODE unsigned char #define OK 0 #define ERROR 1 typedef struct tag_stTableItem { int iData; tag_stTableItem * pstNext; }TABLEITEM, * PTABLEITEM; #define SLL_SEEK_END_NODE(pstHeadNode, pstEndNode)/ {/ / } PTABLEITEM Table[MAX] = {0}; STATUSCODE Insert(PTABLEITEM pstTable, PTABLEITEM pstItem) { // if(NULL == pstTable) { return ERROR; } if(NULL == pstItem) { return OK; } //哈希算法 unsigned char ucOffset = (pstItem->iData) % (MAX); if(NULL == pstTable + ucOffset) { // pstTable[ucOffset] = pstItem; } else { // PTABLEITEM pstEndNode = NULL; SLL_SEEK_END_NODE(pstHeadNode, pstEndNode); if(NULL == pstEndNode) { return ERROR; } // pstEndNode->pstNext = pstItem; } return OK; } int _tmain(int argc, _TCHAR* argv[]) { return 0; }
一點思考:
哈希表、樹、鏈表存儲都有兩種方式:局部變量和申請內存。前者適合比較小數據的存儲,優點是不用維護內存,後者是和大容量存儲,但要記得free。
有兩個問題需要注意:
一、我們操作的時候,經常聲明個局部變量,然後把它掛到表上去,類似pstNode->pstNext = &XXX,但是有沒有想過當這個人函數彈出了,局部變量也就銷毀了,如果表沒了,也就罷了,如果表還在,會有什麼後果?——很嚴重,你掛在表上的數據已經不是那個變量了!
解決辦法:
1、不要掛局部變量,malloc一塊內存,掛上去;
2、掛全局變量;
3、如果非要掛局部變量,保證其生命週期與表相同,或者比表還長。
一般使用第一種方法,全局變量謹慎使用,佔內存。
二、掛了個局部變量到表上去,銷毀表的時候(不管局部變量生命週期是否結束)free這些節點。
問題又來了,掛上去的局部變量又不是malloc的,怎麼能free呢?malloc和free一定是成對使用的。
解決辦法:
1、全部使用malloc,不掛什麼變量,不管是局部的還是全局的;
2、全部掛局部變量,不釋放,等函數結束後自動銷毀。
一般都使用第一種方法。如果執意要混合使用,就等著出問題吧。。。
冒泡排序:
//快速排序 void BubbleSort(int array[], int n) { int i, j, flag, temp; // for(i = 0; i < n -1; i++) { flag = 1; // for(j = 0; j < n - i - 1; j++) { if(array[j] > array[j + 1]) { temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; flag = 0; } } //printf("%d ", i); // if(1 == flag) { break; } } return; } // int _tmain(int argc, _TCHAR* argv[]) { int iArray[7] = {1, 2, 3, 4, 5, 6, 7}; BubbleSort(iArray, 7); return 0; }
快速排序:
//参照《数据结构》(C语言版) //调用:quicksort-->qsort-->partitions int Partitions(int a[], int low, int high) { int iPivotkey = a[low]; while(low < high) { while(low < high && a[high] >= iPivotkey) { --high; } a[low] = a[high]; while(low < high && a[low] <= iPivotkey) { ++low; } a[high] = a[low]; } a[low] = iPivotkey; return low; } // void Qsort(int a[], int low, int high) { int iPivottag; if(low < high) { //递归调用 iPivottag = Partitions(a, low, high); Qsort(a, low, iPivottag - 1); Qsort(a, iPivottag + 1, high); } return; } // void QuickSort(int a[], int n) { Qsort(a, 0, n); } //简单示例 #include <stdio.h> void _tmain() { int i, a[11] = {0, 11, 12, 5, 6, 13, 8, 9, 14, 7, 10}; // for(i = 0; i < 11; printf("=", a[i]), ++i); printf("/n"); QuickSort(a, 10); // for(i = 0; i<11; printf("=", a[i]), ++i); printf("/n"); return; }