redis导入和导出

redis导入和导出

Leave a comment

vagrant 同步目录文件区分大小写

vagrant 同步目录文件区分大小写

[php]

vagrant plugin install vagrant-winnfsd

config.vm.network “private_network” , ip: “172.16.1.139”

config.vm.synced_folder “D:/phpStudy2016/WWW”, “/var/www/html”, type: “nfs”

[/php]

Leave a comment

yaf cli模式

[php]

<?php
/*
* 执行action 方式
* php cli.php request_uri=”/pay/order/clidemo”
*
*/

define(‘APPLICATION_PATH’, dirname(__FILE__) . ‘/..’);
date_default_timezone_set(‘Asia/Shanghai’);

$request = new Yaf_Request_Simple();

function exception_handler($exception){
error_log(“Uncaught exception: “. $exception->getMessage());
}

set_exception_handler(‘exception_handler’);

$app = new Yaf_Application(APPLICATION_PATH . “/conf/application.ini”);
$app->getDispatcher()->dispatch(new Yaf_Request_Simple());

[/php]

Leave a comment

linux php7 安装redis memcached yaf

linux (centos) php7 安装redis memcached yaf

一:安装memcached

[php]

yum install zlib-devel

wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz

tar -zxf libmemcached-1.0.18.tar.gz

./configure –prefix=/usr/local/libmemcached –with-memcached

make && make install

wget https://github.com/php-memcached-dev/php-memcached/archive/php7.zip

unzip php7.zip

cd  php-memcached-php7/

phpize

./configure –with-php-config=/usr/bin/php-config  –with-libmemcached-dir=/usr/local/libmemcached –disable-memcached-sasl

make && make install

[/php]

 

二:安装redis

[php]
sudo pecl install redis

[/php]

三:安装yaf

[php]

sudo pecl install yaf

cd /etc/php.d/
sudo vim redis.ini
; Enable gd extension module

extension=redis.so

 

重启nginx php-fpm

sudo /etc/init.d/nginx restart
sudo service php-fpm restart

[/php]

1 Comment

mac install php7

mac install php7 by brew

最近几年一直在LNMP环境下进行开发,其中的PHP还是5.5版本,有点老旧,去年12月PHP7已经正式发布,新增了一些语法特性,最大的亮点是性能的提升,所以一直想升级到PHP7,由于时间关系一直拖到现在。到写本文为止PHP最新版本为:7.0.9的stable,所以稳定性上基本不用担心。

之前写的 MAC下安装LNMP环境 是用brew安装的,这次升级PHP7继续使用brew, 安装/升级软件很方便。

升级brew

brew update

配置

brew tap homebrew/dupes
brew tap homebrew/versions  
brew tap homebrew/homebrew-php

安装PHP7

brew install php70

遇到的问题

安装提示:

➜  ~ brew install php70
==> Installing php70 from homebrew/php
Error: Cannot install homebrew/php/php70 because conflicting formulae are installed.

  php55: because different php versions install the same binaries.

Please `brew unlink php55` before continuing.

Unlinking removes a formula's symlinks from /usr/local. You can
link the formula again after the install finishes. You can --force this
install, but the build may fail or cause obscure side-effects in the
resulting software.

根据提示执行: brew unlink php55
继续安装: brew install php70

配置文件

安装好后生成的配置文件都在 /usr/local/etc/php/7.0 目录里,分别如下:

php.ini /usr/local/etc/php/7.0/php.ini 
php-fpm.conf /usr/local/etc/php/7.0/php-fpm.conf
php, phpize, php-config ls /usr/local/opt/php70/bin
php-fpm /usr/local/opt/php70/sbin/php-fpm

加入开机启动

mkdir -p ~/Library/LaunchAgents
ln -sfv /usr/local/opt/php70/homebrew.mxcl.php70.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php70.plist

命令行配置

vim ~/.zshrc

export PATH="$(brew --prefix php55)/bin:$PATH"
替换为
export PATH="$(brew --prefix homebrew/php/php70)/bin:$PATH"

alias php-fpm.start="launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php55.plist"
alias php-fpm.stop="launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.php5.plist"
alias php-fpm.restart='php-fpm.stop && php-fpm.start'

修改为

alias php-fpm.start="launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php70.plist"
alias php-fpm.stop="launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.php70.plist"
alias php-fpm.restart='php-fpm.stop && php-fpm.start'

重新加载配置文件

source ~/.zshrc

验证版本

PHP版本

➜  ~ /usr/local/opt/php70/bin/php -v
PHP 7.0.9 (cli) (built: Jul 21 2016 14:50:47) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies

php-fpm版本

➜  ~ /usr/local/opt/php70/sbin/php-fpm -v
PHP 7.0.9 (fpm-fcgi) (built: Jul 21 2016 14:50:51)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies

启动PHP-FPM

执行: php-fpm.start

检查是否启动成功:

➜  ~ ps aux|grep php-fpm
qloog           60380   0.2  0.0  2432792    604 s001  R+    6:00PM   0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn php-fpm
qloog           60378   0.0  0.0  2473348    620   ??  S     6:00PM   0:00.00 /usr/local/opt/php70/sbin/php-fpm --fpm-config /usr/local/etc/php/7.0/php-fpm.conf
qloog           60377   0.0  0.0  2473348    648   ??  S     6:00PM   0:00.00 /usr/local/opt/php70/sbin/php-fpm --fpm-config /usr/local/etc/php/7.0/php-fpm.conf
qloog           60372   0.0  0.0  2475396   7844   ??  S     6:00PM   0:00.03 /usr/local/opt/php70/sbin/php-fpm --fpm-config /usr/local/etc/php/7.0/php-fpm.conf

安装扩展

yaf

brew install php70-yaf

配置文件
/usr/local/etc/php/7.0/conf.d/ext-yaf.ini

memcached

brew install php70-memcached

配置文件
/usr/local/etc/php/7.0/conf.d/ext-memcached.ini

redis

brew install php70-redis

配置文件
/usr/local/etc/php/7.0/conf.d/ext-redis.ini

xdebug

brew install php70-xdebug

配置文件
/usr/local/etc/php/7.0/conf.d/ext-xdebug.ini

swoole

brew install php70-swoole

配置文件
/usr/local/etc/php/7.0/conf.d/ext-swoole.ini

更多扩展执行 brew install 扩展名 进行安装

Leave a comment

Elasticsearch 5.0 golang php 使用

Elasticsearch 5.0 golang  php 使用

之前公司使用Elasticsearch 2.3 版本做搜索引擎,后来Elasticsearch 直接升级为5,api变化较大,服务器升级,应用的golang和php 也升级下

Elasticsearch 5.0 php 文档api地址:

Elasticsearch-PHP

一: golang 链接 创建索引
[php]

package main

import (
“flag”
“fmt”
“io/ioutil”
“log”

//”gopkg.in/olivere/elastic.v3″
“golang.org/x/net/context”
“gopkg.in/olivere/elastic.v5”
)

var (
showVersion = flag.Bool(“version”, false, “print version string”)

indexname = flag.String(“index”, “”, “elasticsearch index name”)
esurl = flag.String(“esurl”, “”, “elasticsearch url: http://host:port”)
//mapping = flag.String(“mapping”, “”, “elasticsearch mapping json config”)
//maxInFlight = flag.Int(“max-in-flight”, 200, “max number of messages to allow in flight”)
)

func LoadFile(filename string) (filedata string, err error) {
fileDataByte, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println(“Read failed”, err)
return
}

filedata = string(fileDataByte)
return
}

func main() {
flag.Parse()
if *showVersion {
fmt.Printf(“esadmin v%s\n”, “0.1”)
return
}

if *indexname == “” || *esurl == “” {
log.Fatal(“–index and –esurl are required”)
}

mappingData, _ := LoadFile(“etc/esmapping/” + *indexname + “.json”)
client, _ := elastic.NewClient(elastic.SetURL(*esurl))
_, err := client.CreateIndex(*indexname).BodyString(mappingData).Do(context.Background())
if err != nil {
// Handle error
panic(err)
}
log.Println(“elasticsearch mapping has been created”)
}

[/php]

 
二:php下载
https://github.com/elastic/elasticsearch-php

composer install 安装vendor包

php Elasticsearch 5.0 扩展包代码下载:
 

download magneto

download magneto

1 Comment

golang tcp服务器/客户端聊天

golang tcp服务器/客户端聊天,使用net包,服务端实现聊天信息的群体广播, 记录所有连接到服务器的客户端信息,
客户端使用gorountine,通道阻塞,根据用户输入的信息发送。

server.go

[php]

package main

import (
“bufio”
“fmt”
“net”
)

// 用来记录所有的客户端连接
var ConnMap map[string]*net.TCPConn

func main() {
var tcpAddr *net.TCPAddr
ConnMap = make(map[string]*net.TCPConn)
tcpAddr, _ = net.ResolveTCPAddr(“tcp”, “127.0.0.1:9999”)

tcpListener, _ := net.ListenTCP(“tcp”, tcpAddr)

defer tcpListener.Close()

for {
tcpConn, err := tcpListener.AcceptTCP()
if err != nil {
continue
}

fmt.Println(“A client connected : ” + tcpConn.RemoteAddr().String())
// 新连接加入map
ConnMap[tcpConn.RemoteAddr().String()] = tcpConn
go tcpPipe(tcpConn)
}

}

func tcpPipe(conn *net.TCPConn) {
ipStr := conn.RemoteAddr().String()
defer func() {
fmt.Println(“disconnected :” + ipStr)
conn.Close()
}()
reader := bufio.NewReader(conn)

for {
message, err := reader.ReadString(‘\n’)
if err != nil {
return
}
fmt.Println(conn.RemoteAddr().String() + “:” + string(message))
// 这里返回消息改为了广播
boradcastMessage(conn.RemoteAddr().String() + “:” + string(message))
}
}

func boradcastMessage(message string) {
b := []byte(message)
// 遍历所有客户端并发送消息
for _, conn := range ConnMap {
conn.Write(b)
}
}
[/php]

client.go

[php]
package main

import (
“bufio”
“fmt”
“net”
)

func main() {
var tcpAddr *net.TCPAddr
tcpAddr, _ = net.ResolveTCPAddr(“tcp”, “127.0.0.1:9999”)

conn, _ := net.DialTCP(“tcp”, nil, tcpAddr)
defer conn.Close()
fmt.Println(“connected!”)

go onMessageRecived(conn)

// 控制台聊天功能加入
for {
var msg string
fmt.Scanln(&msg)
if msg == “quit” {
break
}
b := []byte(msg + “\n”)
conn.Write(b)
}
}

func onMessageRecived(conn *net.TCPConn) {
reader := bufio.NewReader(conn)
for {
msg, err := reader.ReadString(‘\n’)
fmt.Println(msg)
if err != nil {
quitSemaphore <- true break } } } [/php] 开两个命令行窗口 go build server.go ./server go build client.go ./client

Leave a comment

php python 线程池 多线程爬虫

php 线程池 多线程 实现抓取程序

[php]

<?php

class Connect extends Worker  //worker模式
{

public function __construct()
{

}

public function getConnection()
{
if (!self::$ch)
{
self::$ch = curl_init();
curl_setopt(self::$ch, CURLOPT_TIMEOUT, 2);
curl_setopt(self::$ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt(self::$ch, CURLOPT_HEADER, 0);
curl_setopt(self::$ch, CURLOPT_NOSIGNAL, true);
curl_setopt(self::$ch, CURLOPT_USERAGENT, “Firefox”);
curl_setopt(self::$ch, CURLOPT_FOLLOWLOCATION, 1);
}

/* do some exception/error stuff here maybe */

return self::$ch;
}

public function closeConnection()
{
curl_close(self::$ch);
}

/**
* Note that the link is stored statically, which for pthreads, means thread local
* */
protected static $ch;

}

class Query extends Threaded
{

public function __construct($url)
{
$this->url = $url;
}

public function run()
{
$ch = $this->worker->getConnection();
curl_setopt($ch, CURLOPT_URL, $this->url);
$page = curl_exec($ch);
$info = curl_getinfo($ch);
$error = curl_error($ch);
$this->deal_data($this->url, $page, $info, $error);

$this->result = $page;
}

function deal_data($url, $page, $info, $error)
{
$parts = explode(“.”, $url);

$id = $parts[1];
if ($info[‘http_code’] != 200)
{
$this->show_msg($id, $error);
} else
{
$this->show_msg($id, “OK”);
}
}

function show_msg($id, $msg)
{
echo $id.”\t$msg\n”;
}

public function getResult()
{
return $this->result;
}

protected $url;
protected $result;

}

function check_urls_multi_pthreads()
{
global $check_urls;  //定义抓取的连接
$check_urls = array( ‘http://xxx.com’ => “xx网”,);
$pool = new Pool(10, “Connect”, array()); //建立10个线程池
foreach ($check_urls as $url => $name)
{
$pool->submit(new Query($url));
}
$pool->shutdown();
}

check_urls_multi_pthreads();

[/php]

python 多线程

[php]

def handle(sid)://这个方法内执行爬虫数据处理
pass
class MyThread(Thread):
“””docstring for ClassName”””
def __init__(self, sid):
Thread.__init__(self)
self.sid = sid

def run():
handle(self.sid)

threads = []
for i in xrange(1,11):
t = MyThread(i)
threads.append(t)
t.start()

for t in threads:
t.join()

[/php]

python 线程池爬虫
[python]
from queue import Queue
from threading import Thread, Lock
import urllib.parse
import socket
import re
import time

seen_urls = set([‘/’])
lock = Lock()

class Fetcher(Thread):
def __init__(self, tasks):
Thread.__init__(self)
self.tasks = tasks
self.daemon = True

self.start()

def run(self):
while True:
url = self.tasks.get()
print(url)
sock = socket.socket()
sock.connect((‘localhost’, 3000))
get = ‘GET {} HTTP/1.0\r\nHost: localhost\r\n\r\n’.format(url)
sock.send(get.encode(‘ascii’))
response = b”
chunk = sock.recv(4096)
while chunk:
response += chunk
chunk = sock.recv(4096)

links = self.parse_links(url, response)

lock.acquire()
for link in links.difference(seen_urls):
self.tasks.put(link)
seen_urls.update(links)
lock.release()

self.tasks.task_done()

def parse_links(self, fetched_url, response):
if not response:
print(‘error: {}’.format(fetched_url))
return set()
if not self._is_html(response):
return set()
urls = set(re.findall(r”'(?i)href=[“‘]?([^\s”‘<>]+)”’,
self.body(response)))

links = set()
for url in urls:
normalized = urllib.parse.urljoin(fetched_url, url)
parts = urllib.parse.urlparse(normalized)
if parts.scheme not in (”, ‘http’, ‘https’):
continue
host, port = urllib.parse.splitport(parts.netloc)
if host and host.lower() not in (‘localhost’):
continue
defragmented, frag = urllib.parse.urldefrag(parts.path)
links.add(defragmented)

return links

def body(self, response):
body = response.split(b’\r\n\r\n’, 1)[1]
return body.decode(‘utf-8′)

def _is_html(self, response):
head, body = response.split(b’\r\n\r\n’, 1)
headers = dict(h.split(‘: ‘) for h in head.decode().split(‘\r\n’)[1:])
return headers.get(‘Content-Type’, ”).startswith(‘text/html’)

class ThreadPool:
def __init__(self, num_threads):
self.tasks = Queue()
for _ in range(num_threads):
Fetcher(self.tasks)

def add_task(self, url):
self.tasks.put(url)

def wait_completion(self):
self.tasks.join()

if __name__ == ‘__main__’:
start = time.time()
pool = ThreadPool(4)
pool.add_task(“/”)
pool.wait_completion()
print(‘{} URLs fetched in {:.1f} seconds’.format(len(seen_urls),time.time() – start))
[/python]

Leave a comment

Memcached 学习笔记

1、memcached -m 64 -vv -f 1.25 -I 100k -R 20, 其中-vv -f -I -R分别指什么?
-vv 显示更详细的信息
-f chunk的增幅因子,默认1.25.chunk的大小根据这个增幅因子增长.
-I 设置slab page的大小,即设置可以保存的item的最大值,默认1mb,最小是1k,最大值128m.
-R 每一个事件(event)的最大请求数,限制最大请求数可以防止线程饥饿,默认是20.

2、Memcached 是否可以存储图片?最长的过期时间是多久?默认配置下,是否可以存储10m的文本字符串?
memcached为key->value非关系型数据库,key为一般字串,值唯一。value除了php中的资源不能存,其它的数据都能存储(字符串、数值、数组、对象、布尔值、null、二进制<图片、视频>),但是都以字符串的形式存储。
如果是一个从现在算起的以秒为单位的数字,这个 秒数不能超过60×60×24×30(30天时间的秒数);如果失效的值大于这个值, 服务端会将其作为一个真实的Unix时间戳来处理而不是 自当前时间的偏移。如果失效值被设置为0(默认),此元素永不过期(但是它可能由于服务端为了给其他新的元素分配空间而被删除)。
Memcached默认对Key和Value长度做如下限制: Key字符串的长度不能超过255个字符;
Value字符串的长度不能超过1024 * 1024个字符, 即存储数据不能超过1M.

3、memcached常用来存储什么数据?memcached是否会主动删除过期的数据?memcached如何实现分布式存储?
字符串.
不会.
memcached虽然称为”分布式”缓存服务器,但服务器端并没有”分布式”的功能.memcached的分布式完全是由客户端实现的.

4、假如memcached分配的内存已被用完,存储新值会发生什么情况?
memcached在内存空间不足的时候,会使用lru算法进行空间分配,将最近最不常使用的空间腾出来给刚加入的item使用.

5、memcached如何检查自本次读取后,在写入操作时检查值是否已经发生了变化?
Memcached::cas — 比较并交换值
Memcached::cas()执行一个“检查并设置”的操作,因此,它仅在当前客户端最后一次取值后,该key 对应的值没有被其他客户端修改的情况下, 才能够将值写入。检查是通过cas_token参数进行的, 这个参数是Memcach指定给已经存在的元素的一个唯一的64位值, 怎样获取这个值请查看Memcached::get*() 系列方法的文档。注意:这个值作为double类型是因为PHP的整型空间限制。
译注:这是Memcached扩展比Memcache扩展一个非常重要的优势, 在这样一个系统级(Memcache自身提供)的冲突检测机制(乐观锁)下, 我们才能保证高并发下的数据安全。

6、如何优化memcached存储和命中率?
造成memcached的内存使用率降低的属性有:
1)page中从来没有被使用过chunks.
2)chunk中存放数据和chunk实际大小的差值.
3)由于短时间的数据集中在某个slab区域,导致大量page被分配,而之后被闲置的内存,这些即使有整个page的空闲也不会被分配给实际压力很大的slab区域.

缓存命中率 = get_hits/cmd_get * 100% (总命中次数/总请求次数)
要提高命中率,预估value大小并且适当调整内存页大小和增长因子是必须的.
命中率的提升可以通过多种方案实现:
1)提高服务获取的内存总量.
2)提高空间利用率,这实际上也是另一种方式的增加内存总量.
3)对于整体命中率,可以采取有效的冗余策略.减少分布式服务时某个server发生服务抖动的情况.

7、为什么memcached总是会浪费一些内存空间?为什么不推荐在memcached存储较大(比如接近1m)的数据项?
内存被分成大小不等的slabs chunks(先分成大小相等的slabs,然后每个slab被分成大小相等chunks,不同slab的chunk大小是不相等的).每个chunk是由item(key和value)填充的,不同大小的chunk被不同大小的item填充,当chunk不能被item填充满的时候,那chunk中那些剩余的空间不会被再利用,就被浪费了.
Memcached存储单个item最大数据是在1MB内,如果数据超过1M,存取set和get是都是返回false,而且引起性能的问题。

8、memcached常用来存储什么数据,又是如何实现分布式存储的?
常用来以字符串方式存储包括图像,视频,文件等.
memcached的分布式算法:
1. 余数分散法,就是“根据服务器台数的余数进行分散”。 求得键的整数哈希值,再除以服务器台数,根据其余数来选择服务器。
余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点。 那就是当添加或移除服务器时,缓存重组的代价相当巨大。 添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器, 从而影响缓存的命中率。为了在解决这个问题,实现了另一种分布式算法:hash一致性算法。
2.hash一致性算法(Consistent Hashing)
首先求出memcached服务器(节点)的哈希值, 并将其配置到0~232的圆(continuum)上。 然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。 然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。 如果超过232仍然找不到服务器,就会保存到第一台memcached服务器上.

9、如何理解memcached当中slab class、page、chunk三者的关系?
很多张A4纸,有的A4纸有100格,有的A4纸有200格,把相同格子的纸分别订成作业本.不同格子的作业本就是slab class, 每个作业本的每张纸就是page, 每张纸里的格子就是chunk.

10、相比memcached,redis的关键特点是什么?
1)Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
2)Redis支持数据的备份,即master-slave模式的数据备份。
3)Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

11、将一组包含文章信息([id,标题,创建时间,浏览数]…)数组存到redis,用redis的什么数据类型?
哈希.

12、session在什么情况下推荐存储到memcached等缓存当中?
多web服务共享session数据.

13、memcached的内存分配策略是怎样的?
向memcached添加一个item时候,emcached首先会根据item的大小,来选择最合适的slab class,计算好所要放入的chunk之后,memcached会去检查该类大小的chunk还有没有空闲的,如果没有,将会申请1M(1个page)的空间并划分为该种类chunk,并会用去一个chunk,当当前所有chunk使用完之后,下次再有一个符合条件的item添加进来时,memcached会再次申请一个1M(1个page)的空间提供使用.如果所有的page都存储满了,并且memcached也已不能再分配新的内存空间,memcached将根据lru算法(近期最少使用的),清除某个item并将新项存储到该位置.

14、mongodb可以处理海量数据的关键特性是什么?
1)面向集合(Collection-Oriented)
2)模式自由(schema-free):集合里面没有列和行的概念
3)文档型(documents)
4)支持动态查询
5)支持完全索引,包括内部对象(唯一索引和普通索引同样支持)
6)支持高效的二进制的数据存储,包括大型对象(如视频、图片)
7)自动处理碎片
8)文件存储格式是BSON(一种JSON的扩展)

15、分布式数据系统的cap定理如何理解?
我们用一台服务器A对外提供存储服务,为了避免这台服务器宕机导致服务不可用,我们又在另外一台服务器B上运行了同样的存储服务。每次用户在往服务器A写入数据的时候,A都往服务器B上写一份,然后再返回客户端。一切都运行得很好,用户的每份数据都存了两份,分别在A和B上,用户访问任意一台机器都能读取到最新的数据。
这时不幸的事情发生,A和B之间的网络断了导致A和B无法通信,也就是说网络出现了分区,那么用户在往服务器A写入数据的时候,服务器A无法将该数据写入到服务器B。这时,服务器A就必须要做出一个艰难的选择:
要么选择一致性(C)而牺牲可用性(A):为了保证服务器A和B上的数据是一致的,服务器A决定暂停对外提供数据写入服务,从而保证了服务器A和B上的数据是一致,但是牺牲了可用性。
要么选择可用性(A)而牺牲一致性(C):为了保证服务不中断,服务器A先把数据写入到了本地,然后返回客户端,从而让客户端感觉数据已经写入了。这导致了服务器A和B上的数据就不一致了。

8 Comments

Linux c 单向链表

Linux c 单向链表,实现约瑟夫环问题,每3个数被踢出

[c]

#include <stdio.h>
#include <stlib.h>
#define JOSE_NR = 8;
struct node_st
{
/* data */
int data;
struct node_st *next;
};

struct node_st *jose_create(int n)
{
struct node_st *me,*newnode;
me=malloc(sizeof(*me));
int i=1;
if(me == NULL)
return NULL

me->data = i;
me->next=me;
i++;

cur = me;
for (; i <= n; i++)
{
/* code */
newnode=malloc(sizeof(*newnode));
if(newnode == NULL)
return NULL
nownode->data = i;
newnode->next = me;

cur->next= newnode;
cur = newnode;

}
return me;

}

void jose_show(struct node_st *me)
{
struct node_st *list=me;

for (list= me; list->next != me; list = list->next)
{
/* code */
sleep(1);
printf(“%d\n”, list->data);
fflush(NULL);//刷新缓冲区

}

printf(“%d\n”,list->data);

}

void jose_kill(struct node_st **me,int n)
{
struct node_st *cur = *me,*node;
int i =1 ;

while(cur != cur->next){
while(i < n)
{
node = cur;
cur = cur->next;
i++;
}
printf(“%d\n”, cur->data);
node->next= cur->next;
free(cur);

cur= node->next;
i=1;
}
*me = cur;
printf(“\n”);

}
int main()
{
/* code */
//无头单项循环链表(约瑟夫环问题)

struct node_st *list;
int num=8;
int n=3;
list = jose_create(JOSE_NR);
jose_show(list);
jose_kill(&list,n);
jose_show(list);

return 0;
}

[/c]

make 编译后

simple-link

2 Comments