• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 183,  comments - 10,  trackbacks - 0
             

            面試題 100 —— 5 查找 Top K

            這里的做法是利用一個堆,用這個堆作為 K 個元素的輸出容器,堆的特點是可以以 O(1) 的效率去堆中最大/小的元素。
            正式利用了這一點,這種方法的時間復雜度為 O(NlogK)

            查找最小的 K 個數
            利用最大堆
            思路時,開始的時候堆為空,堆中元素個數還不足 K 個,所以遍歷的當前元素直接加入到堆中
            當堆中元素等于 K 的時候,檢查當前元素與堆中最大元素的大小關系,若大于最大元素則忽略,否則將堆中最大元素刪除,并將當前元素添加到堆中。
            整個過程,遍歷一遍集合,每次針對當前元素需要對堆進行調整,總的時間復雜度為 O(NlogK)

            http://www.shnenglu.com/jake1036/archive/2011/05/16/146466.html

            代碼實現:

             1 #include <iostream>
             2 #include <vector>
             3 #include <set>
             4 using namespace std;
             5 
             6 typedef vector<int> dataset;
             7 typedef multiset<int, greater<int> > bigheap;
             8 
             9 void findTopK(bigheap& bh, const dataset& ds, int k)
            10 {
            11  bh.clear();
            12  for (dataset::const_iterator cit = ds.begin(); cit != ds.end(); ++cit)
            13  {
            14   if (bh.size() < k)
            15   {
            16    bh.insert(*cit);
            17   }
            18   else
            19   {
            20    bigheap::iterator it = bh.begin();
            21    if (*it > *cit)
            22    {
            23     bh.erase(it);
            24     bh.insert(*cit);
            25    }
            26   }
            27  }
            28 }
            29 
            30 int main()
            31 {
            32  dataset ds;
            33  for (int i = 100; i != 0--i)
            34  {
            35   ds.push_back(i);
            36  }
            37  bigheap bh;
            38  findTopK(bh, ds, 10);
            39  for (bigheap::const_iterator cit = bh.begin(); cit != bh.end(); ++cit)
            40  {
            41   cout << *cit << endl;
            42  }
            43  return 0;
            44 }
            45 
            46 


            posted @ 2011-07-12 17:46 unixfy 閱讀(301) | 評論 (0)編輯 收藏

            :: 和同學聊了起來
            =======================
            信息論的角度去討論算法
            一個算法的高效不高效
            看它產生的信息量有多大
            如果有冗余的信息量,效率就有提高的空間

            舉個例子
            你統計一個集合中重復出現的元素
            那么久沒有必要對元素計數
            直觀的方法是對元素計數
            然后檢測
            但是這個計數是冗余的
            只需要找到重復的,不需要知道具體出現的次數
            針對這個問題

            我是覺得最高效的算法應該是恰恰能解決現有問題的算法,不生成多余的冗余信息
            生成任何信息都是需要代價的
            信息論。。。
            算法的高效不高效,一是時間二是空間
            上面那個問題,既然不需要計數
            只需要給每個元素一個位,節省空間
            位圖
            海量數據的時候
            如果 幾十億個 int 數
            看里面是否存在重復的
            重復出現的時候,檢測到對應為為 1 ,說明之前存在了
            所以就是重復出現的數
            遍歷這個集合
            可以將結果存起來
            我的意思是,這個問題就是找到重復出現的,沒有必要對每個數計數
            這樣,就可以節省空間

            還有時間的
            還有就是充分挖掘問題中的信息
            充分利用問題中的信息,提高獲取的信息量,充分利用了隱藏的信息量就會涉及出高效的算法
            基于比較的算法,不會是 O(N) 的,最優就是 O(NlogN)。
            基數排序、桶排序,這樣的就是有限制性的算法,這個限制就是元素有個范圍,限制是給了隱含的信息,利用這個可以就有了 O(N) 的排序
            盡可能從問題中挖掘潛在的信息,獲得的信息越多越有利于解決問題,也就越有可能獲得高效的解法。

            控制論、系統論、信息論
            信息論是香農創建的,也屬于數學,算法就是解決問題的,解決問題的就是想得到結果,結果就是一種信息,算法的設計可以用信息論的角度解釋
            反正總結起來是兩點吧,一是充分挖掘已有的信息,二是盡可能不要產生冗余信息。這樣設計的算法,既可以利用以存在的信息,也不會產生多余的信息,效率自然會高。

            ======================

            FOO 21:57:39
            信息論的角度去討論算法
            FOO 21:57:57
            一個算法的高效不高效
            FOO 21:58:09
            看它產生的信息量有多大
            FOO 21:58:36
            如果有冗余的信息量,效率就有提高的空間
            BAR 22:00:18

            FOO 22:00:53
            呵呵
            FOO 22:01:05
            后面的幾句是我最近感受的
            BAR 22:01:11
            呵呵
            BAR 22:01:14
            我不懂
            FOO 22:01:17

            BAR 22:01:20
            我還是碼農級別的
            FOO 22:01:23

            FOO 22:01:27
            舉個例子
            FOO 22:01:57
            你統計一個集合中重復出現的元素
            FOO 22:02:10
            那么久沒有必要對元素計數
            FOO 22:02:16
            直觀的方法是對元素計數
            FOO 22:02:27
            然后檢測
            FOO 22:02:38
            但是這個計數是冗余的
            FOO 22:02:51
            只需要找到重復的,不需要知道具體出現的次數
            FOO 22:02:55
            針對這個問題
            BAR 22:03:28

            BAR 22:04:14
            你繼續
            BAR 22:04:11
             
            FOO 22:04:24
            我是覺得最高效的算法應該是恰恰能解決現有問題的算法,不生成多余的冗余信息
            FOO 22:04:33
            生成任何信息都是需要代價的
            FOO 22:04:36
            信息論。。。
            BAR 22:04:41
            你先說上面那個問題
            FOO 22:06:05
            算法的高效不搞笑,一是時間二是空間
            FOO 22:06:14
            上面那個問題,既然不需要計數
            BAR 22:06:20
            上面那個問題什么方法好?
            FOO 22:06:29
            只需要給每個元素一個位,節省空間
            FOO 22:06:43
            位圖吧
            FOO 22:06:44
            呵呵
            BAR 22:06:50
            那你怎么做
            FOO 22:06:51
            海量數據的時候
            FOO 22:07:00
            如果 幾十億個 int 數
            BAR 22:07:08
            把位置1
            BAR 22:07:14
            第二次出現呢
            FOO 22:07:15
            看里面是否存在重復的
            BAR 22:07:20
            也就是重復的時候出現呢
            BAR 22:07:00
            一個元素出現了一次
            FOO 22:07:53
            重復出現的時候,檢測到對應為為 1 ,說明之前存在了
            BAR 22:08:00
            是撒
            FOO 22:08:03
            所以就是重復出現的數
            BAR 22:08:05
            你只找一個么
            FOO 22:08:11
            所有
            BAR 22:08:17
            還是說你有另一個輸出結果的地方
            FOO 22:08:22
            遍歷這個集合
            FOO 22:08:36
            可以將結果存起來
            BAR 22:08:41
            就是出現重復的時候把這個重復的放到另外一個地方或者輸出
            FOO 22:09:07

            BAR 22:09:22
            恩,我先洗澡去了
            FOO 22:09:31
            我的意思是,這個問題就是找到重復出現的,沒有必要對每個數計數
            FOO 22:09:36
            這樣,就可以節省空間
            FOO 22:09:51
            還是時間的
            FOO 22:14:58
            還有就是充分挖掘問題中的信息
            FOO 22:15:38
            充分利用問題中的信息,提高獲取的信息量,充分利用了隱藏的信息量就會涉及出高效的算法
            FOO 22:16:11
            基于比較的算法,不會是 O(N) 的,最優就是 O(NlogN)。
            FOO 22:17:09
            基數排序、桶排序,這樣的就是有限制性的算法,這個限制就是元素有個范圍,限制是給了隱含的信息,利用這個可以就有了 O(N) 的排序
            FOO 22:17:37
            盡可能從問題中挖掘潛在的信息,獲得的信息越多越有利于解決問題,也就越有可能獲得高效的解法。

            FOO 22:18:04
            呵呵
            FOO 22:18:23
            控制論、系統論、信息論
            FOO 22:19:47
            信息論是香農創建的,也屬于數學,算法就是解決問題的,解決問題的就是想得到結果,結果就是一種信息,算法的設計可以用信息論的角度解釋,呃。。
            FOO 22:21:24
            反正總結起來是兩點吧,一是充分挖掘已有的信息,二是盡可能不要產生冗余信息。這樣設計的算法,既可以利用以存在的信息,也不會產生多余的信息,效率自然會高。

             

            posted @ 2011-07-11 23:18 unixfy 閱讀(204) | 評論 (0)編輯 收藏

            給一個字符串,找到連續的最長數字字符串的長度和地址

            掃描一遍,類似最大連續子串的做法

             1 #include <iostream>
             2 #include <string>
             3 #include <cctype>
             4 using namespace std;
             5 
             6 string foo(const string& str)
             7 {
             8     string ret, tmp;
             9     string::size_type i, j, left, right;
            10     i = 0;
            11     j = 0;
            12     left = right = 0;
            13     bool first = true;
            14     for (string::size_type k = 0; k != str.size(); ++k)
            15     {
            16         if (isdigit(str[k]))
            17         {
            18             if (first)
            19             {
            20                 first = false;
            21                 i = k;
            22                 j = k;
            23             }
            24             else
            25             {
            26                 j = k;
            27             }
            28         }
            29         else
            30         {
            31             first = true;
            32             if ((j - i) > (right - left))
            33             {
            34                 left = i;
            35                 right = j;
            36             }
            37             i = j = k;
            38         }
            39     }
            40     ret = str.substr(left, right - left + 1);
            41     return ret;
            42 }
            43 
            44 int main()
            45 {
            46     string str;
            47     while (cin >> str)
            48     {
            49         cout << foo(str) << endl;
            50     }
            51     return 0;
            52 }
            53 


            posted @ 2011-07-11 14:31 unixfy 閱讀(151) | 評論 (0)編輯 收藏

            思路就是先排序,O(NlogN)
            然后一次遍歷排序后的集合

            在具體遍歷的過程中,需要有個策略
            詳見代碼

            需要有兩個相鄰的滑標,比較相鄰的元素是否相等
            但是為了避免重復計入,需要設置一個標志位,來表示是否是組里面的第一個元素

            如果相鄰的兩個元素不相等,則表示前面組檢測結束,需要檢查記錄這個組的集合是否為空
            若不為空,則將其加入結果中,并且要情況這個輔助組和標志位

             1 #include <iostream>
             2 #include <vector>
             3 #include <algorithm>
             4 using namespace std;
             5 
             6 void foo(vector<vector<int> >& ret, const vector<int>& dataset)
             7 {
             8     ret.clear();
             9     if (dataset.size() <= 1)
            10     {
            11         return;
            12     }
            13     vector<int>::size_type i, j;
            14     bool f = false;    
            15     vector<int> tmp;
            16     for (i = 0, j = 1; i != dataset.size() - 1++i, ++j)
            17     {
            18         if (dataset[i] == dataset[j])
            19         {
            20             if (!f)
            21             {
            22                 f = true;
            23                 tmp.push_back(dataset[i]);
            24                 tmp.push_back(dataset[j]);
            25             }
            26             else
            27             {
            28                 tmp.push_back(dataset[j]);
            29             }
            30         }
            31         else
            32         {
            33             if (!tmp.empty())
            34             {
            35                 ret.push_back(tmp);
            36                 tmp.clear();
            37                 f = false;
            38             }
            39         }
            40     }
            41 }
            42 
            43 int main()
            44 {
            45     vector<int> dataset;
            46     for (int i = 0; i < 10++i)
            47     {
            48         dataset.push_back(i);
            49     }
            50     dataset.push_back(5);
            51     dataset.push_back(3);
            52     dataset.push_back(5);
            53     dataset.push_back(8);
            54     sort(dataset.begin(), dataset.end());
            55 
            56     vector<vector<int> > ret;
            57     foo(ret, dataset);
            58     for (vector<vector<int> >::size_type i = 0; i != ret.size(); ++i)
            59     {
            60         for (vector<int>::size_type j = 0; j != ret[i].size(); ++j)
            61         {
            62             cout << ret[i][j] << ' ';
            63         }
            64         cout << endl;
            65     }
            66 
            67     return 0;
            68 }
            69 


            posted @ 2011-07-11 13:53 unixfy 閱讀(260) | 評論 (0)編輯 收藏

            一個字符串集合

            {"...", "...", ... }

            找到相同的字符串,這樣的字符串是:包含的字符相同,字符的個數也相同

            解決方案:
            先對每個字符串排序
            然后對排完序的字符串整體排序
            遍歷整個字符串集合,即可得到結果

             1 #include <iostream>
             2 #include <vector>
             3 #include <map>
             4 #include <string>
             5 #include <algorithm>
             6 using namespace std;
             7 
             8 int main()
             9 {
            10     vector<string> data;
            11     data.push_back("cafe");
            12     data.push_back("baidu");
            13     data.push_back("duiba");
            14     data.push_back("thisone");
            15     data.push_back("iseasy");
            16     data.push_back("esayis");
            17     data.push_back("siesay");
            18     data.push_back("esaysi");
            19 
            20     multimap<stringstring> mem;
            21     for (vector<string>::size_type i = 0; i != data.size(); ++i)
            22     {
            23         string tmp(data[i]);
            24         sort(tmp.begin(), tmp.end());
            25         mem.insert(make_pair(tmp, data[i]));
            26     }
            27     if (mem.size() <= 1)
            28     {
            29         return 0;
            30     }
            31     for (multimap<stringstring>::const_iterator cit = mem.begin(); cit != mem.end(); ++cit)
            32     {
            33         cout << cit->first << '\t' << cit->second << endl;
            34     }
            35     cout << "===================" << endl;
            36     multimap<stringstring>::const_iterator cit1, cit2, cit3;
            37     cit1 = mem.begin();
            38     cit3 = cit1;
            39     cit2 = ++cit3;
            40     bool f = false;
            41     while (cit2 != mem.end())
            42     {
            43         if (cit1->first == cit2->first)
            44         {
            45             if (!f)
            46             {
            47                 f = true;
            48                 cout << cit1->first << '(' << cit1->second << ')' << '\t' << cit2->first << '(' << cit2->second << ')' << '\t';
            49             }
            50             else
            51             {
            52                 cout << cit2->first << '(' << cit2->second << ')' << '\t';
            53             }
            54         }
            55         else
            56         {
            57             if (f)
            58             {
            59                 cout << endl;
            60                 f = false;
            61             }
            62         }
            63         ++cit1;
            64         ++cit2;
            65     }
            66     return 0;
            67 }
            68 

             


            posted @ 2011-07-11 13:34 unixfy 閱讀(532) | 評論 (0)編輯 收藏

            Linux 內核編譯升級記錄

            先是裝了個 VMware
            然后再里面裝了個 CentOS

            之后就是漫長的內核編譯升級

            上周周四、周五兩天都在忙這個,但是最終沒有成功
            內核編譯一次需要花費一個小時,在虛擬機里面

            一開始編譯的時候,出現錯誤。
            主要存在兩個錯誤,剛開始不知道為什么,也沒有對出現的問題進行解決,只是重新編譯,結果當然失敗

            第一個運行錯誤是
            “insmod: error inserting ‘/lib/dm-region-hash.ko”
            Google 了一下,是因為 init 里存在重復行,vi 編輯刪除之

            第二個錯誤是:
            “Volume group "VolGroup00" not found”
            Google 了一下,是因為 .config 文件的配置問題
            需要將
            General setup --->
            enable deprecated sysfs features
            勾選了

            這兩個問題解決后,Linux 內核升級即可完成。
            下面說一下具體的步驟:

            1.
            下載最新版本的 Linux 內核
            http://www.kernel.org/
            這里是 linux-2.6.37.6.tar.bz2
            拷到 /usr/src

            2.
            加壓 *.tar.bz2
            root# tar -jvxf linux-2.6.37.6.tar.bz2

            3.
            進入 linux-2.6.37.6 文件夾
            # cd linux-2.6.37.6

            # make clean
            # make mvproper

            4.
            配置
            make menuconfig
            注意,就是這里要勾選
            General setup --->
            enable deprecated sysfs features
            否則會造成
            “Volume group "VolGroup00" not found”
            錯誤

            5.
            編譯
            # make all

            6.
            安裝
            # make modules_install
            # make install

            7.
            設置
            # mkinitrd /boot/initrd-2.6.37.6.img 2.6.37.6
            # cp arch/x86/boot/bzImage /boot/vmlinuz-2.6.37.6
            # cp /usr/src/linux-2.6.37.6/System.map /boot/System.map-2.6.37.6

            8. 修改默認啟動內核
            # cat /etc/grub.conf
            # vi /etc/grub.conf
            將 default=1 修改為
            default=0

            9.
            刪除多余行,這是編譯的一個小 bug ,造成出現重復行
            會造成
            “insmod: error inserting ‘/lib/dm-region-hash.ko”
            的錯誤

            # cp /boot/initrd-2.6.37.6.img /tmp/
            # cd /tmp/
            # mkdir newinitrd
            # cd newinitrd
            # zcat ../initrd-2.6.37.6.img | cpio -i
            # ls
            # vi init
            刪除 init 中存在的重復
            echo “Loading dm-region-hash.ko module”
            insmod /lib/dm-region-hash.ko
            兩行
            保存

            # find . | cpio -c -o > ../initrd
            # cd ..
            # gzip -9 < initrd > initrd-2.6.37.6.img
            # ls
            # mv /boot/initrd-2.6.37.6.img /home/
            # cp initrd-2.6.37.6.img /boot/
            # reboot

            進入新內核后,查看新內核的版本
            # uname -a
            # uname -r

            ===================================================
            下面是我在升級過程中的命令記錄 history
              543  tar -jvxf linux-2.6.37.6.tar.bz2
              544  clear
              545  cd linux-2.6.37.6
              546  ls
              547  make clean
              548  make mvproper
              549  clear
              550  make all
              551  make clean
              552  make mrporper
              553  make menuconfig
              554  make menuconfig
              555  \
              556  \
              557  cd /usr/src/linux-2.6.37.6
              558  ls
              559  ls -a
              560  make all
              561  clear
              562  make modules_install
              563  make install
              564  mkinitrd /boot/initrd-2.6.37.6.img 2.6.37.6
              565  rm /boot/initrd-2.6.37.6.img
              566  ls
              567  ls /boot/
              568  mkinitrd /boot/initrd-2.6.37.6.img 2.6.37.6
              569  cp arch/x86/boot/bzImage /boot/vmlinuz-2.6.37.6
              570  cp /usr/src/linux-2.6.37.6/System.map /boot/System.map-2.6.37.6
              571  cat /etc/grub.conf
              572  cp /boot/initrd-2.6.37.6.img /tmp/
              573  cd /tmp/
              574  rm -rf newinitrd/
              575  mkdir newinitrd
              576  cd newinitrd/
              577  zcat ../initrd-2.6.37.6.img | cpio -i
              578  ls
              579  vi init
              580  find . | cpio -c -o > ../initrd
              581  cd ..
              582  gzip -9 < initrd > initrd-2.6.37.6.img
              583  ls
              584  mv /boot/initrd-2.6.37.6.img /home/
              585  cp initrd-2.6.37.6.img /boot/
              586  reboot
              587  uname -r
              588  uname -a
              589  uname -r
              590  history


            ======================================================

            網上查的資料,主要是第一個和第二個
            http://www.linuxidc.com/Linux/2010-09/28735.htm
            http://blog.csdn.net/douzi24/article/details/5781148
            http://hi.baidu.com/mhlovejn/blog/item/7a4a55fe65de7488b801a020.html/
            http://blog.csdn.net/cdsnmdl/article/details/3922513
            http://www.cublog.cn/u/9483/showart_2524232.html
            http://blog.csdn.net/do2jiang/article/details/4965967
            http://my.chinaunix.net/space.php?uid=113544&do=blog&id=85646
            http://www.shnenglu.com/momoxiao/archive/2010/06/26/118758.html

            posted @ 2011-07-11 11:22 unixfy 閱讀(447) | 評論 (1)編輯 收藏

            最短摘要的生成

            這個問題在《編程之美》中提到過。前幾天百度三面的時候也問到了這個問題,當時沒有答上來。從新翻閱了一下《編程之美》。
            直觀的解決方案是:
            從文檔第一個詞開始遍歷,尋找后面的詞是否與關鍵詞數組匹配
            然后從文檔第二個、第三個 ... 一直到最后一個詞遍歷

            這個過程要記錄最短文摘的信息。
            這個時間復雜度是 O(N ^ 2 * M)
            N 是文檔的長度
            M 是關鍵詞數組的大小

            改進的方法是:
            對于求的的一個文摘,記錄第一次出現關鍵詞的位置,然后直接移動到該關鍵詞,然后右邊的邊界再向后移動。
            這個時間復雜度是 O(N)
            這種方法也就是說維持了一個摘要滑動窗口,一遍掃描文檔即可得到相應的最短摘要。
            摘要中的關鍵詞可以用一個隊列來存儲,因為摘要滑動窗口的左邊界和右邊界都是要從左到右移動的。所以隊列正好適用。另外還應該維持一個對應文摘滑動窗口中的關鍵詞出現的次數表。在做左右邊界移動時需要考量這個次數表所提供的信息。

            posted @ 2011-07-03 20:34 unixfy 閱讀(1085) | 評論 (0)編輯 收藏

            N 個元素的入棧出棧序列總共有多少種?
            我們用 0 表示入棧,1 表示出棧
            假設有 6 個元素:
            則有
            0 0 0 0 0 0 1 1 1 1 1 1
            0 1 0 1 0 1 0 1 0 1 0 1

            還有其他位置的情況,總共有多種?
            我們知道這是一個 12 位的序列
            窮舉有 2 ^ 12 個序列,有的不能滿足棧的入棧和出棧邏輯
            也就是說:
            任何一個元素,首先需要里面有 6 個 0 和 6 個 1,然后再統計包括它在內的前的 0 個個數是否小于 1 的個數,如果小于則不符合
            如果統計到第 12 個元素,如果符合,則是正確的序列。(時間上只需要檢測到第 11 個元素)

             1 #include <iostream>
             2 using namespace std;
             3 
             4 bool test(int k, int n)
             5 {
             6     int count = 0;
             7     int temp = k;
             8     for (; temp != 0; temp &= temp - 1++count);
             9     if (count != n)
            10     {
            11         return false;
            12     }
            13 
            14     int zero = 0;
            15     int t = n + n - 1;    // 只需要檢測到 n + n - 2 位
            16     for (int i = 0; i < t; ++i)
            17     {
            18         if ((k & (1 << i)) == 0)
            19         {
            20             ++zero;
            21         }
            22         else
            23         {
            24             if (--zero < 0)
            25             {
            26                 return false;
            27             }
            28         }
            29     }
            30     return true;
            31 }
            32 
            33 // n : 元素的個數
            34 int foo(int n)
            35 {
            36     int t = 1 << (n + n);
            37     int ret = 0;
            38     for (int k = 0; k < t; ++k)
            39     {
            40         if (test(k, n))
            41         {
            42             ++ret;
            43             // 輸出
            44             cout << ret << ":" << endl;
            45             for (int i = 0; i < n + n; ++i)
            46             {
            47                 if ((k & (1 << i)) == 0)
            48                 {
            49                     cout << 0 << ' ';
            50                 }
            51                 else
            52                 {
            53                     cout << 1 << ' ';
            54                 }
            55             }
            56             cout << endl;
            57         }
            58     }
            59     return ret;
            60 }
            61 
            62 int main()
            63 {
            64     int n;
            65     while (cin >> n)
            66     {
            67         cout << foo(n) << endl;
            68     }
            69     return 0;
            70 }

            http://www.wming.com/a/articles/devlanguage/c/2011/0101/81478_%E6%8E%A8%E8%8D%90%E5%BC%BA%E5%A5%B8%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4%E4%B8%80%E4%B8%AA%E7%AC%94%E8%AF%95%E9%A2%98.html
            http://topic.csdn.net/u/20091017/01/37370E0B-A736-40A5-8839-D8D0B9FCAADA.html
            http://hi.csdn.net/baihacker
            http://hi.baidu.com/feixue
            http://hi.baidu.com/jumay426/blog/item/50b1ca84b5198726c65cc3f8.html
            http://www.shnenglu.com/life02/archive/2009/10/17/98851.html

            posted @ 2011-07-02 13:51 unixfy 閱讀(271) | 評論 (0)編輯 收藏
            基本原理是一樣的,都是順序掃描中綴表達式,用一個操作符棧進行中間處理。
            牽涉運算符優先級。
            過去是按照是操作符還是操作數處理,對于操作符做比較混亂的邏輯判斷。
            這里分別對操作數,加減乘除左括號右括號進行分別處理,邏輯更簡單。
            程序的邏輯結構在于分解。
             1 // 中綴轉后綴
             2 // 原汁原味
             3 
             4 #include <stdio.h>
             5 #include <string.h>
             6 #include <stdlib.h>
             7 #define MAX 100
             8 
             9 char* infixToPostfix(char postfix[], char infix[])
            10 {
            11     static char stack[MAX];
            12     int top = 0, ch, i = 0, j = 0;
            13     ch = infix[i++];
            14     while (ch != '#')
            15     {
            16         switch (ch)
            17         {
            18         case '(':
            19             stack[top++= ch;
            20             break;
            21         case ')':
            22             while (top > 0 && stack[top - 1!= '(')
            23             {
            24                 postfix[j++= stack[--top];
            25             }
            26             --top;
            27             break;
            28         case '+':
            29         case '-':
            30             while (top > 0 && stack[top - 1!= '(')
            31             {
            32                 postfix[j++= stack[--top];
            33             }
            34             stack[top++= ch;
            35             break;
            36         case '*':
            37         case '/':
            38             while (top > 0 && (stack[top - 1== '*' || stack[top - 1== '/'))
            39             {
            40                 postfix[j++= stack[--top];
            41             }
            42             stack[top++= ch;
            43             break;
            44         case ' ':
            45             break;
            46         default:
            47             postfix[j++= ch;
            48         }
            49         ch = infix[i++];
            50     }
            51     while (top > 0)
            52     {
            53             postfix[j++= stack[--top];
            54     }
            55     postfix[j++= '\0';
            56     return postfix;
            57 }
            58 
            59 int main()
            60 {
            61     char infix[MAX];
            62     char stack[MAX];
            63     char postfix[MAX];
            64 
            65     scanf("%s", infix);
            66     infixToPostfix(postfix, infix);
            67     printf("%s\n", infix);
            68     printf("%s\n", postfix);
            69     return 0;
            70 }

            posted @ 2011-06-30 20:36 unixfy 閱讀(144) | 評論 (0)編輯 收藏

            表達式的運算

            總共分兩個步驟
            ·中綴表達式轉換成后綴表達式
            ·后綴表達式的計算

            中綴表達式轉換成后綴表達式:
            掃描一遍中綴表達式
            操作符棧
            左括號和右括號的特殊性
            運算符的優先級

            后綴表達式的計算:
            掃描一遍后綴表達式
            操作數棧
            當前操作符,操作數棧出棧計算,注意雙目運算符的左右順序

            表達式運算的整個過程,利用了兩個棧
            ·操作符棧
            ·操作數棧
            分別應用于第一和第二步驟中。

            在做中綴表達式轉換成后綴表達式的過程中需要注意左括號和右括號的入棧出棧,其他操作符相對左括號和右括號的入棧和出棧。注意左括號的棧內優先級與棧外優先級的區別。


            實現:
              1 //
              2 // 表達式運算
              3 // Mark
              4 // email: goonyangxiaofang AT 163.com
              5 // QQ   : 591247876
              6 // 2011.6.29
              7 // ( ( 1 + 2 ) * 3 + ( 1 + 10 ) ) / 2
              8 // ???
              9 //
             10 
             11 #include <iostream>
             12 #include <string>
             13 #include <vector>
             14 #include <stack>
             15 #include <map>
             16 #include <cstdlib>
             17 using namespace std;
             18 
             19 map<stringint> operatorPriors;
             20 
             21 void getInfix(vector<string>& infix)
             22 {
             23     infix.clear();
             24     string tmp;
             25     while (cin >> tmp)
             26     {
             27         infix.push_back(tmp);
             28     }
             29 }
             30 
             31 void init()
             32 {
             33     operatorPriors["+"= 10;
             34     operatorPriors["-"= 10;
             35     operatorPriors["*"= 20;
             36     operatorPriors["/"= 20;
             37     operatorPriors["%"= 20;
             38     operatorPriors["("= 30;
             39     operatorPriors[")"= 0;
             40 }
             41 
             42 bool prior(const string& op1, const string& op2)
             43 {
             44     return operatorPriors[op1] > operatorPriors[op2];
             45 }
             46 
             47 bool isOperator(const string& s)
             48 {
             49     return operatorPriors.find(s) != operatorPriors.end();
             50 }
             51 
             52 void print(stack<string> operators)
             53 {
             54     while (!operators.empty())
             55     {
             56         cout << operators.top() << ' ';
             57         operators.pop();
             58     }
             59     cout << endl;
             60 }
             61 
             62 const vector<string>& infixToPostfix(vector<string>& postfix, const vector<string>& infix)
             63 {
             64     postfix.clear();
             65     stack<string> operators;
             66     for (vector<string>::size_type i = 0; i != infix.size(); ++i)
             67     {
             68         if (isOperator(infix[i]))
             69         {
             70             if (operators.empty())
             71             {
             72                 operators.push(infix[i]);
             73             }
             74             else if (operators.top() == "(" && infix[i] != ")" || prior(infix[i], operators.top()))
             75             {
             76                 operators.push(infix[i]);
             77             }
             78             else
             79             {
             80                 if (infix[i] == ")")
             81                 {
             82                     while (operators.top() != "(")
             83                     {
             84                         postfix.push_back(operators.top());
             85                         operators.pop();
             86                     }
             87                     operators.pop();
             88                 }
             89                 else
             90                 {
             91                     postfix.push_back(operators.top());
             92                     operators.pop();
             93                     while (!operators.empty() && !prior(infix[i], operators.top()) && operators.top() != "(")
             94                     {
             95                         postfix.push_back(operators.top());
             96                         operators.pop();
             97                     }
             98                     
             99                     operators.push(infix[i]);
            100                 }
            101             }
            102         }
            103         else
            104         {
            105             postfix.push_back(infix[i]);
            106         }
            107     }
            108     while (!operators.empty())
            109     {
            110         postfix.push_back(operators.top());
            111         operators.pop();
            112     }
            113     return postfix;
            114 }
            115 
            116 double stringToDouble(const string& s)
            117 {
            118     return (atof(s.c_str()));
            119 }
            120 
            121 double evalPost(const vector<string>& post)
            122 {
            123     stack<double> operands;
            124     int a, b;
            125     for (vector<string>::size_type i = 0; i != post.size(); ++i)
            126     {
            127         if (post[i] == "+")
            128         {
            129             b = operands.top();
            130             operands.pop();
            131             a = operands.top();
            132             operands.pop();
            133             operands.push(a + b);
            134         }
            135         else if (post[i] == "-")
            136         {
            137             b = operands.top();
            138             operands.pop();
            139             a = operands.top();
            140             operands.pop();
            141             operands.push(a - b);
            142         }
            143         else if (post[i] == "*")
            144         {
            145             b = operands.top();
            146             operands.pop();
            147             a = operands.top();
            148             operands.pop();
            149             operands.push(a * b);
            150         }
            151         else if (post[i] == "/")
            152         {
            153             b = operands.top();
            154             operands.pop();
            155             a = operands.top();
            156             operands.pop();
            157             operands.push(a / b);
            158         }
            159         else if (post[i] == "%")
            160         {
            161             b = operands.top();
            162             operands.pop();
            163             a =operands.top();
            164             operands.pop();
            165             operands.push(a - b);
            166         }
            167         else
            168         {
            169             // stringstream ss;
            170             // ss << post[i];
            171             // ss >> a;
            172             operands.push(stringToDouble(post[i]));
            173         }
            174     }
            175     return operands.top();
            176 }
            177 
            178 int main()
            179 {
            180     init();
            181     vector<string> infix;
            182     vector<string> postfix;
            183     getInfix(infix);
            184     infixToPostfix(postfix, infix);
            185     for (vector<string>::size_type i = 0; i != postfix.size(); ++i)
            186     {
            187         cout << postfix[i] << ' ';
            188     }
            189     cout << endl;
            190     cout << evalPost(postfix) << endl;
            191     return 0;
            192 }


            posted @ 2011-06-29 01:58 unixfy 閱讀(152) | 評論 (0)編輯 收藏
            僅列出標題
            共19頁: First 4 5 6 7 8 9 10 11 12 Last 
            yy6080久久| 久久久久久国产精品无码超碰| 久久精品18| 99久久成人18免费网站| 日本久久中文字幕| 久久91精品国产91久久户| 日韩欧美亚洲国产精品字幕久久久 | 亚洲精品乱码久久久久久蜜桃图片 | 无遮挡粉嫩小泬久久久久久久| 中文字幕亚洲综合久久| 久久亚洲sm情趣捆绑调教| 久久久久久狠狠丁香| 亚洲va久久久噜噜噜久久狠狠| 久久综合视频网站| 999久久久免费精品国产| 无码人妻久久一区二区三区蜜桃 | 精品熟女少妇a∨免费久久| 亚洲国产精品无码久久九九| 99久久国产综合精品成人影院| 亚洲AV日韩精品久久久久久久| 久久亚洲天堂| 久久精品国产国产精品四凭| 久久精品国产福利国产秒| 少妇久久久久久久久久| 2021国内久久精品| 热久久视久久精品18| 色综合久久天天综线观看| 精品久久久久中文字| 久久精品99久久香蕉国产色戒 | 久久人人爽人人爽人人片AV不| 国产精品99久久久精品无码| 久久久精品国产Sm最大网站| 日本三级久久网| 国产福利电影一区二区三区久久久久成人精品综合 | 国产高清美女一级a毛片久久w| 国产精品久久久久影院色| 97久久天天综合色天天综合色hd| 久久精品水蜜桃av综合天堂| 久久精品亚洲中文字幕无码麻豆| 国产高潮国产高潮久久久| 91久久精品91久久性色|