算法匯總


算法設計應該滿足特點:正確性、可使用性、可讀性、健壯性、高效率低存儲性

算法具有的特征:有限性、確定性、可行性、輸入性、輸出性

二叉樹遞歸求和算法:

typedef struct BNode
{
int date;
struct BNode* lchild, * rchild;
}BTNode;

int Submt(BTNode* bt)
{
if (bt->lchild == NULL && bt->rchild == NULL)
return bt->date;
return Submt(bt->lchild) + Submt(bt->rchild) + bt->date;
}

遞歸求解數組最大值:

int fmax(int a[], int i)
{
if (i == 1)
return a[0];
return max(fmax(a, i - 1),a[i-1]);
}

遞歸刪除單鏈表中所有數據:

void Destroy(ListNode* p)
{
if (p->next != NULL)
{
Destroy(p);
free(p);
}
}

二叉樹遞歸查找x路徑

bool Findxpath(BTNode *bt, int x, vector<int> temp, vector<int>& path)
{
if (bt == NULL)
return false;
temp.push_back(bt->date);
if (bt->date == x)
{
path = temp;
return true;
}
bool find = Findxpath(bt->lchild, x, temp, path);
if (find)
return true;
Findxpath(bt->rchild, x, temp, path);
}

遞歸輸出各個位數的數字

void Find(int n)
{
if (n != 0)
{
Find(n / 10);
printf("%d", n % 10);
}
}

選擇排序算法

void SelectSort(int a[], int n, int i)
{
int j,k;
if (i == n - 1)
return;
k = i;
for (j = i + 1; j < n; j++)
{
if (a[k] > a[j])
k = j;
}
if (k != i)
swap(a[i], a[k]);
SelectSort(a, n, i + 1);
}

分治法的時間復雜度

image-20210630100005664

快速排序用分治法實現:

int Partitionx(int a[], int s, int t)
{
   int i = s , j = t;
   int tmp = a[s]; //用序列的第1個記錄作為基准
   while (i != j) //從序列兩端交替向中間掃描,直至i=j為止    
  {
       while (j > i && a[j] >= tmp)
           j--;   //從右向左掃描,找第1個關鍵字小於tmp的a[j]
       a[i] = a[j]; //將a[j]前移到a[i]的位置
       while (i < j && a[i] <= tmp)
           i++;   //從左向右掃描,找第1個關鍵字大於tmp的a[i]
       a[j] = a[i]; //將a[i]后移到a[j]的位置
  }
   a[i] = tmp;
   return i;

}

void QuickSort(int a[], int l, int r)
{
   if (r <= l) return;
   int i = Partitionx(a, l, r);
   QuickSort(a, l, i - 1);
   QuickSort(a, i + 1, r);
}

自頂向下的二路歸並排序算法

void Merge(int a[],int low,int mid,int high)
//a[low..mid]和a[mid+1..high]→a[low..high]
{
int* tmpa;
int i = low,j = mid + 1,k = 0;
tmpa = (int*)malloc((high - low + 1) * sizeof(int));
while (i <= mid && j <= high)
if (a[i] <= a[j]) //將第1子表中的元素放入tmpa中
{
tmpa[k] = a[i];  i++; k++;
}
else //將第2子表中的元素放入tmpa中
{
tmpa[k] = a[j]; j++; k++;
}
while (i <= mid) //將第1子表余下部分復制到tmpa
{
tmpa[k] = a[i]; i++; k++;
}
while (j <= high) //將第2子表余下部分復制到tmpa
{
tmpa[k] = a[j]; j++; k++;
}
for (k = 0,i = low; i <= high; k++,i++)  //將tmpa復制回a中
a[i] = tmpa[k];
free(tmpa); //釋放tmpa所占內存空間
}

void MergePass(int a[],int length,int n)
//一趟二路歸並排序
{
int i;
for (i = 0; i + 2 * length - 1 < n; i = i + 2 * length)   //歸並length長的兩相鄰子表
Merge(a,i,i + length - 1,i + 2 * length - 1);
if (i + length - 1 < n)     //余下兩個子表,后者長度小於length
Merge(a,i,i + length - 1,n - 1); //歸並這兩個子表
}

void sort(int a[],int n) //二路歸並算法
{
int length;
for (length = 1; length < n; length = 2 * length)
MergePass(a,length,n);
}

折半查找(logn)

int BinSearch(int a[],int low,int high,int k)
{
    int mid;
    if (low <= high)		//當前區間存在元素時
    {
        mid = (low + high) / 2;	//求查找區間的中間位置
        if (a[mid] == k)		//找到后返回其物理下標mid
            return mid;
        if (a[mid] > k)		//當a[mid]>k時
            return BinSearch(a,low,mid - 1,k);
        else			//當a[mid]<k時
            return BinSearch(a,mid + 1,high,k);
    }
    else return -1;		//若當前查找區間沒有元素時返回-1
}

查找最大和次大元素(n)

void solve(int a[],int low,int high,int &max1,int &max2)
{
    if (low == high)
    {
        max1 = a[low]; max2 = max1;
    }
    else if (low == high - 1)
    {
        max1 = max(a[low], a[high]);
        max2 = min(a[low], a[high]);
    }
    else
    {
        int mid = (low + high) / 2;
        int lmax1, lmax2;
        solve(a, low, mid, lmax1, lmax2);
        int rmax1, rmax2;
        solve(a, mid + 1, high, rmax1, rmax2);
        if (lmax1 > rmax1)
        {
            max1 = lmax1;
            max2 = max(lmax2, rmax1);
        }
        else
        {
            max1 = rmax1;
            max2 = max(lmax1, rmax2);	//lmax1,rmax2中求次大元素
        }
    }
}

尋找兩個等長有序序列的中位數(logn)

int midnum(int a[],int s1,int t1,int b[],int s2,int t2)
{  //求兩個有序序列a[s1..t1]和b[s2..t2]的中位數
  int m1,m2;
  if (s1==t1 && s2==t2)     //兩序列只有一個元素時返回較小者
    return a[s1]<b[s2]?a[s1]:b[s2];
  else
  {  m1=(s1+t1)/2;		//求a的中位數
     m2=(s2+t2)/2;		//求b的中位數
     if (a[m1]==b[m2])	//兩中位數相等時返回該中位數
      return a[m1];
     if (a[m1]<b[m2])	//當a[m1]<b[m2]時
     {   postpart(s1,t1);	//a取后半部分
        prepart(s2,t2);	//b取前半部分
       return midnum(a,s1,t1,b,s2,t2);
     }
      else			//當a[m1]>b[m2]時
      {  prepart(s1,t1);	//a取前半部分
        postpart(s2,t2);	//b取后半部分
        return midnum(a,s1,t1,b,s2,t2);
     }
  }
}

棋盤覆蓋問題

void ChessBoard(int tr, int tc, int dr, int dc, int size)
{
    if (size == 1) return;
    int t = tile++;     //取出L,牌號為t
    int s = size / 2;   //分解棋盤
    if (dr < tr + s && dc < tc + s) //控制象限,大小於號控制
        ChessBoard(tr, tc, dr, dc, s);
    else
    {
        board[tr + s - 1][tr + s - 1] = t;  //控制棋盤,左上
        //board[tr+s][tr+s-1],右上
        //board[tr+s-1][tr+s],左下
        //board[tr+s][tr+s],右下
        ChessBoard(tr, tc, tr + s - 1, tc + s - 1, s);
    }
}

image-20210701144802771

0-1背包問題正好等於重量

void dfs(int i, int tw, int tv, int rw, int op[])   //rw為剩余可裝重量
{
    int j;
    if (i > n)		//一個葉子結點找到
    {
        if (tw = W && tv > maxv)    //找到一個滿足條件的更優解,保存
        {
            maxv = tv;
            for (j = 1; j <= n; j++)	//復制最優解
            {
                x[j] == op[j];
            }
        }
    }
    else 		//尚未找完所有物品
    {
        if (tw + w[i] <= W)    //左孩子結點剪枝 
        {
            op[i] = 1;			//選取第i個物品
            dfs(i + 1, tw + w[i], tv + v[i], rw - w[i], op);
        }
        if (tw + rw - w[i] >= W)
        {
            op[i] = 0;		//不選取第i個物品,回溯
            dfs(i + 1, tw, tv, rw - w[i], op);
        }
    }
}

求解最短路徑

#define MAXN 51
#define INF 0x3f3f3f3f
int n;	//個數
int a[MAXN][MAXN];	//矩陣
int v;	//源點
int dist[MAXN];	//到頂點i的最短路徑
int prevx[MAXN];	//前一個頂點

struct Node
{
	int vno;	//編號
	int length;	//長度
};

void bfs(int v)
{
	Node e, e1;
	queue<Node> pqu;
	e.vno = v;
	e.length = 0;
	pqu.push(e);
	dist[v] = 0;
	while (!pqu.empty())
	{
		e = pqu.front();
		e = pqu.pop();
		for (int j = 0; j < n; j++)
		{
			if (a[e.vno][j] < INF && e.length + a[e.vno][j] <= dist[j])	//剪枝
			{
				dist[j] = e.length + a[e.vno][j];
				prevx[j] = e.vno;
				e1.vno = j;
				e1.length = dist[j];
				pqu.push(e1);
			}
		}
	}
}

貪心算法性質:

1、貪心選擇性質

2、最優子結構特征

 

算法設計條件:正確性、可使用性、可讀性、健壯性、高效率低儲存

算法的5個特征:有限性、確定性、可行性、輸入性、輸出性

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM