2020年2月22日 星期六

程式設計師應有的程式技能-C語言資料結構-雙向鏈結範例

详解Linux内核双向循环链表算法的实现(上)
原创tanglinux 最后发布于2012-02-27 18:44:29 阅读数 4153

开发平台:Ubuntu11.04
编译器:gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)
内核源码:linux-2.6.38.8.tar.bz2

    据我们所知,单链表只有一个指向其直接后继的指针域,而且只能从某个结点出发顺着指针域往后寻查其他结点。若要寻查结点的直接前趋,则需要从头指针重新开始。为了克服单链表这种单向性的缺点,可利用双向链表。顾名思义,在双向链表的结点中有两个指针域,其一指向直接后继,另一个指向直接前趋。

    双向循环链表指的是终止结点的next的指针域指向头结点,头结点的prior指针域指向终止结点,如下图所示:



1、一般双向循环链表的实现

例子所用的结构体如下:

#include <stdio.h>
#include <stdlib.h>

typedef int data_type;

typedef struct double_listnode {
    data_type data;
    struct double_listnode *prior, *next;
}double_listnode_t, *double_listnode_p;
 
双向循环链表的运算
(1)、创建(带头结点)
通过循环依次创建n个数据域为整数的结点,示例代码如下:

static double_listnode_t *init_double_list(int n)
{
    int i;
    double_listnode_p head, p, s;
 
    head = (double_listnode_t *)malloc(sizeof(double_listnode_t));
    head -> prior = head -> next = head;

    p = head;
    for (i = 0; i < n; i++) {
s = (double_listnode_t *)malloc(sizeof(double_listnode_t));
s -> data = i + 1;

s -> next = head;
head -> prior = s;

s -> prior = p;
p -> next = s;

p = s;
    }

    return head;
}

(2)、按结点在链表中的位置查找

示例代码如下:


static double_listnode_t *get_double_listnode(double_listnode_p head, int i)
{
    double_listnode_p p = head;
    int j = 0;

    while (p -> next != head && j < i) {
p = p -> next;
j++;
    }

    if (i == j)
return p;
    else
return NULL;
}

(3)、在链表中的i位置插入一个结点

首先要获得i-1结点的地址,然后初始化数据域并插入,示例代码如下:




static void insert_double_listnode(double_listnode_p head, int i, data_type data)
{
    double_listnode_p tmp, p = NULL;

    p = get_double_listnode(head, i - 1);
    if (p == NULL) {
fprintf(stderr, "position error\n");
exit(-1);
    }

    tmp = (double_listnode_t *)malloc(sizeof(double_listnode_t));
    tmp -> data = data;

    tmp -> prior = p;
    tmp -> next = p -> next;

    p -> next -> prior = tmp;
    p -> next = tmp;
}

(4)、删除链表的i结点

先获得i结点的地址,然后删除,示例代码如下:




static void delete_double_listnode(double_listnode_p head, int i)
{
    double_listnode_p p = NULL;

    p = get_double_listnode(head, i);
    if (p == NULL || p == head) {
fprintf(stderr, "position error\n");
exit(-1);
    }

    p -> prior -> next = p -> next;
    p -> next -> prior = p -> prior;

    free(p);
}

(5)、打印链表

示例代码如下:


static void print_double_listnode(double_listnode_p head)
{
    double_listnode_p p = head -> next;

    while (p != head) {
printf("%d ", p -> data);
p = p -> next;
    }
    printf("\n");
}
(6)、销毁链表

示例代码如下:


static void destroy_double_list(double_listnode_p head)
{
    double_listnode_p s, p = head -> next;

    while (p != head) {
s = p;
p = p -> next;
free(s);
    }
    free(head);
}

综合测试上述所讲函数的代码如下:


int main(void)
{
    int a = 10;
    double_listnode_p head;

    head = init_double_list(a);
    print_double_listnode(head);

    insert_double_listnode(head, 7, 11);
    print_double_listnode(head);

    delete_double_listnode(head, 5);
    print_double_listnode(head);

    destroy_double_list(head);

    return 0;
}

    综合测试代码的功能是先创建10个结点的双向循环链表,然后在链表的第7位插入一个数据域为11的结点,再然后删除链表的第5个结点,最后销毁整个链表。综合测试代码输出结果如下:

1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 11 7 8 9 10
1 2 3 4 6 11 7 8 9 10

————————————————
版权声明:本文为CSDN博主「tanglinux」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/npy_lp/article/details/7294494

【資料引用資訊】
google關鍵字:详解Linux内核双向循环链表算法的实现(上)

程式設計師應有的程式技能-C語言-建立開發環境

第一部分 安裝工具

Linux程式設計第01篇:建立C和C++的環境,在Linux下寫C和C++的程式

 facebook PLURK twitter
一般撰寫C或C++語言都是在微軟Windows系列下撰寫,今天要來使用Linux環境下撰寫,因為Linux是免費的作業軟體,而且非常適合架設伺服器,基於這個原因,我想要在Linux環境下來學習C及C++等語言,不過要學習之前,要先建立好環境,這件事在微軟的作業系統環境下也是很重要的,沒先把環境建立好,後續根本沒辦法編譯及執行程式。
Linux的發行版本很多,有Red Hat、CentOS、Fedora、Ubuntu等等,基於方便性及普遍性,我決定使用Ubuntu Server 16.04 LTS版本,其作業系統下載網址:

為方便學習,我使用VMware Workstation 12,模擬Ubuntu作業系統,有關VM的使用方法在此無敘述,請自行上網查詢。

Ubuntu進入畫面

要在Linux環境下撰寫C和C++,需要以下3種軟體:
1-安裝編譯器:Linux的C和C++編譯器分別稱為gccg++,請鍵入以下指令:

sudo apt-get install gcc g++

輸入密碼後,將開始下載及安裝


完成後分別輸入:

gcc -v

g++ -v
檢查有無安裝完成,出現上面2個圖案內容即為完成安裝。
2-安裝build-essential:這是一個很重要的東西,一定要安裝,沒有安裝gcc和g++都沒辦法編譯及輸出,而且會出現很多錯誤訊息。

請輸入:

sudo apt-get install build-essential


輸入密碼後開始安裝


3-安裝編輯器vim:vim就如同Windows下的文字編輯器,可以讓我們編寫程式,Ubuntu預設下只有vi,沒有vim,因為vi屬於舊版編輯器,不是很好用,所以我們要安裝vim編輯器,所以請輸入:
sudo apt-get install vim

輸入密碼後開始安裝
如果安裝完上述3個必備軟體後,我們可以開始在Linux的作業系統下開始寫C或C++語言程式囉!!

【資料引用資訊】
google關鍵字:Linux程式設計第01篇:建立C和C++的環境,在Linux下寫C和C++的程式

第二部分 測試安裝工具

日誌2016-02-09 20:00
使用linux寫c語言

 作者:問天
{1}.打開終端機(Terminal):

Debian:




Ubuntu:

{2}.編輯檔案:
$ vim <檔名>
例:$ vim hello.c

{3}.編輯:
 i 進入編輯模式
輸入程式
例:
#include<stdio.h>
int main(void){printf("hello work!\n");return 0;}
Esc退出編輯
輸入 :wq 儲存並退出
w(儲存)、q(退出)

{4}.編譯:
編譯程式碼
$ gcc -o <輸出檔名> <原檔名>
例:$ gcc -o hello hello.c
輸出檔名可有可無,據說預設是 a.out

{5}.執行:
$ ./<檔名>
例:$ ./hello


{6}.結果:


《完》



【資料引用資訊】

google關鍵字:使用linux寫c語言

網址:https://m.gamer.com.tw/home/creationDetail.php?sn=3097436


補充部分 VIM的用法

2012年5月27日 星期日


[Vim] 複製、貼上、搜尋、復原


Vim的複製、貼上、搜尋是簡單的指令,也是常用的指令:
        選擇一段文字,可以在一般模式下鍵入大寫V,或者小寫v來選擇文字區塊。鍵入大寫V是游標經過一行就選擇一行,小寫v則是游標經過的位置就選擇起來。
        選擇好文字區塊後,按下小寫y可以複製起選擇的文字,按下d可以刪除掉選取的文字。
        在想要貼上文字的地方,按下p就可以貼上剛才複製好的文字。
        如果要復原剛才的動作,可以在一般模式下鍵入u。
        要搜尋字串,可以在一般模式下輸入"/",並在斜線後方鍵入要搜尋的字串,並按下Enter。當找到一個符合的字串後,若要繼續往下搜尋,可以鍵入小寫n。

2019年10月1日 星期二

程式設計師應有的程式技能-ASP.NET(C#)資料庫存取-MVC架構技術

第一部分:資料庫資料表建置


[鐵人賽Day22] ASP.Net Core MVC 進化之路 - Entity Framework Core / Code first


與過去Entity Framework 6相比,
Entity Framework Core(簡稱EF Core)在使用上做了相當的改變,
本文將介紹EF Core的使用方式。

ORM 

如果有接觸過EF6的讀者對ORM這個名詞應該都不陌生。
ORM是什麼呢?
ORM全名為Object Relationship Mapping(物件關聯對應),
主要可以幫助我們用「寫程式」的方式去描述資料庫的結構,
並幫我們實現資料庫的新刪修查的功能,
你可以將它想像成一個幫你跟資料庫溝通的代理人
好處是它可以幫我們將資料自動轉為強型別的物件。

而在.Net中實現ORM的工具有許多種,
Entity Framework系列是微軟官方推出的ORM工具,
它可以使用LINQ的描述方式幫助我們操作資料。
但假如貴公司還是習慣使用純粹的SQL語法操作,
可以考慮使用Dapper這套工具。

Entity Framework Core

EF Core.Net中幫助我們與DB溝通的ORM工具,
跟前一代的EF6相比最大的差別是輕量化與跨平台。
在過去EF6的時候edmx速度相對較慢,
但也真的非常強大XD。
EF Core將過去的Model First拿掉了,
目前的建制方式剩下以下兩種:
  • Code First(純手工的)
  • Code First with Database(從DB來的Code First)

以下將示範使用Code First的建立方式。
首先先建立好一個ASP.Net Core MVC的範本專案,
接著使用Nuget安裝Microsoft.EntityFrameworkCore 。


下面這兩張表描述著Person(人)與Education(學歷)的一對多關係,
我們使用Code First來建立。


DbContext 是EF Core中幫我們與資料庫溝通的類別,
所以我們先建立一個CustomDbContext 並繼承DbContext ,
並使用DbSet<TEntity> 來裝載描述資料表的類別。
public class CustomDbContext : DbContext
{
    public CustomDbContext(DbContextOptions<CustomDbContext> options) : base(options)
    {
    }

    public DbSet<Person> Person { get; set; }
    public DbSet<Education> Education { get; set; }
}

接著先來建立Person及Education類別。
Person.cs
public class Person
{
    [Required]
    public int Id { get; set; }

    [Required]
    [StringLength(20)]
    public string Name { get; set; }
        
    public int? Age { get; set; }
}

Education.cs
public class Education
{
    [Required]
    public int Id { get; set; }

    [StringLength(20)]
    public string SchoolName { get; set; }

    [Required]
    public int GraduatedYeay { get; set; }

    [Required]
    [ForeignKey("Person")]
    public int PersonId { get; set; }
        
    public virtual Person Person { get; set; }
}
 在資料欄位中凡命名包含ID者將會自動被視為主鍵,
你也可以透過 [Key] 自行設定。

[Required] 可設定必要的欄位(不允許Null),
但結構型別(int, double, float, datetime)不得為空值(只會是預設值),
所以使用 int? 方式設定。
 [StringLength()] 則代表字串長度。

好了之後在專案中建立一個dbsetting.json,
裡面會放置連接資料庫需用到的ConnectionStrings
{
  "ConnectionStrings": {
    "SampleDBConnection": "Server=(LocalDB)\\MSSQLLocalDB;Database=SampleDB;"
  }
}

接著修改Program中的組態設定,
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((webHostBuilder, configurationBinder) =>
        {
            configurationBinder.AddJsonFile("dbsetting.json", optional: true);
        })
        .UseStartup<Startup>();

接著在StartupConfigureServices方法加入連接字串設定。
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<CustomDbContext>(options =>
    {
        options.UseSqlServer(Configuration.GetConnectionString("SampleDBConnection"));
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

最後在下面Configure方法中設定每次執行前檢查資料庫是否被建立。
public void Configure(IApplicationBuilder app, CustomDbContext customDbContext)
{
    customDbContext.Database.EnsureCreated();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

你也可以透過Add-Migration指令的方式進行建立,
有興趣的讀者可參考這篇

最後請將程式執行起來後,
使用資料庫連接工具(如SSMS)進行連接,
查看我們剛才建立的資料表。
Person

Education


Code First的內容就先介紹到這邊,
下篇會接著介紹EF CoreCode First From Database的使用方式
若內容有誤在麻煩指正。

參考

【資料引用資訊】
google關鍵字:[鐵人賽Day22] ASP.Net Core MVC 進化之路 - Entity Framework Core / Code first

第二部分:更動資料庫資料表


[C#][MVC5]使用Code First 擴充Identity Table


打從接觸MVC也有快兩年的時光了
但由於公司內部採用既有驗證機制(SSO)
所以對Identity一直沒有什麼接觸
最近碰到趕緊來紀錄一下


首先我們先來建一個新的專案IdentityExtensionTableDemo


按下確定之後
點選變更驗證 -> 個別使用者帳戶


專案範本會自動幫你加入Identity Owin的相關程式碼
後面大家應該就不陌生了
瘋狂下一步就好
開起來之後點選Models -> IdentityModels.cs


IdentityModels.cs


首先我們要從ApplicationUser動手
假設要新增一個Education的Table
所以我們先來新增Education.cs並加入一些基本的屬性


掛上Attribute指定資料型態長度
[Required]會影響到該欄位是否允許NULL


最後要來建關聯了
因為ApplicationUser -> Education是一對多的關係
所以需要在Education裡面記住ApplicationUser的ID
​​
之後還沒結束
記得回到ApplicationUser.cs中宣告一個ICollection<Education>的屬性


好了之後就可以來build我們的schema了
使用Code First務必記得最常用的三個指令

- Enable-Migrations : 會幫你自動在專案下建立一個Migration的資料夾,爾後所有Migration的紀錄都會擺在這
- Add-Migration 當Schema有異動的時候,會幫你建一個Migration(有點類似)
- Update-Database : 在DefaultConnection指定的目標建置資料庫(預設在/App_Data下)

好了之後請先打開套件管理器主控台(Package Manager Console, PMC)


輸入Enable-Migrations


可以看到專案底下多了一個Migrations的資料夾


接著輸入Add-Migration [名稱]


好了之後會自動打開一個.cs檔(放在/Migrations資料夾底下)
裡面會是這次Migration所要調整的東西
因為是第一次建所以內容會比較多一點


最後輸入Update-Database


好了之後回到方案總管
記得要顯示所有檔案(預設會隱藏)
然後點右鍵加入至專案


點兩下後會跳到伺服器總管的畫面


再點兩下快速檢視一下


如果還不確定到底關聯有沒有拉成功
可以用Entity Framework確認一下



這樣就大功告成了
不過眼尖的朋友可能會發現
它幫我產的Education自動加了字尾s
如果想要移掉的話可以在ApplicationDbContext.cs動手腳


最後的程式碼放在GitHub
【資料引用資訊】
google關鍵字:[C#][MVC5]使用Code First 擴充Identity Table